]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #40667 - DaseinPhaos:patch-4, r=GuillaumeGomez
authorCorey Farwell <coreyf@rwell.org>
Tue, 21 Mar 2017 03:45:01 +0000 (23:45 -0400)
committerGitHub <noreply@github.com>
Tue, 21 Mar 2017 03:45:01 +0000 (23:45 -0400)
Fix typo in `ptr` doc

`sizeof` should be `size_of`

249 files changed:
.gitmodules
src/Cargo.lock
src/bootstrap/bin/rustc.rs
src/bootstrap/check.rs
src/bootstrap/doc.rs
src/bootstrap/lib.rs
src/bootstrap/step.rs
src/doc/book [new submodule]
src/doc/book/src/README.md [deleted file]
src/doc/book/src/SUMMARY.md [deleted file]
src/doc/book/src/associated-types.md [deleted file]
src/doc/book/src/attributes.md [deleted file]
src/doc/book/src/bibliography.md [deleted file]
src/doc/book/src/borrow-and-asref.md [deleted file]
src/doc/book/src/casting-between-types.md [deleted file]
src/doc/book/src/chapter_1.md [deleted file]
src/doc/book/src/choosing-your-guarantees.md [deleted file]
src/doc/book/src/closures.md [deleted file]
src/doc/book/src/comments.md [deleted file]
src/doc/book/src/compiler-plugins.md [deleted file]
src/doc/book/src/concurrency.md [deleted file]
src/doc/book/src/conditional-compilation.md [deleted file]
src/doc/book/src/const-and-static.md [deleted file]
src/doc/book/src/crates-and-modules.md [deleted file]
src/doc/book/src/deref-coercions.md [deleted file]
src/doc/book/src/documentation.md [deleted file]
src/doc/book/src/drop.md [deleted file]
src/doc/book/src/effective-rust.md [deleted file]
src/doc/book/src/enums.md [deleted file]
src/doc/book/src/error-handling.md [deleted file]
src/doc/book/src/ffi.md [deleted file]
src/doc/book/src/functions.md [deleted file]
src/doc/book/src/generics.md [deleted file]
src/doc/book/src/getting-started.md [deleted file]
src/doc/book/src/glossary.md [deleted file]
src/doc/book/src/guessing-game.md [deleted file]
src/doc/book/src/if-let.md [deleted file]
src/doc/book/src/if.md [deleted file]
src/doc/book/src/iterators.md [deleted file]
src/doc/book/src/lifetimes.md [deleted file]
src/doc/book/src/loops.md [deleted file]
src/doc/book/src/macros.md [deleted file]
src/doc/book/src/match.md [deleted file]
src/doc/book/src/method-syntax.md [deleted file]
src/doc/book/src/mutability.md [deleted file]
src/doc/book/src/operators-and-overloading.md [deleted file]
src/doc/book/src/ownership.md [deleted file]
src/doc/book/src/patterns.md [deleted file]
src/doc/book/src/primitive-types.md [deleted file]
src/doc/book/src/procedural-macros.md [deleted file]
src/doc/book/src/raw-pointers.md [deleted file]
src/doc/book/src/references-and-borrowing.md [deleted file]
src/doc/book/src/release-channels.md [deleted file]
src/doc/book/src/strings.md [deleted file]
src/doc/book/src/structs.md [deleted file]
src/doc/book/src/syntax-and-semantics.md [deleted file]
src/doc/book/src/syntax-index.md [deleted file]
src/doc/book/src/testing.md [deleted file]
src/doc/book/src/the-stack-and-the-heap.md [deleted file]
src/doc/book/src/trait-objects.md [deleted file]
src/doc/book/src/traits.md [deleted file]
src/doc/book/src/type-aliases.md [deleted file]
src/doc/book/src/ufcs.md [deleted file]
src/doc/book/src/unsafe.md [deleted file]
src/doc/book/src/unsized-types.md [deleted file]
src/doc/book/src/using-rust-without-the-standard-library.md [deleted file]
src/doc/book/src/variable-bindings.md [deleted file]
src/doc/book/src/vectors.md [deleted file]
src/doc/reference
src/doc/unstable-book/src/SUMMARY.md
src/doc/unstable-book/src/plugin.md
src/doc/unstable-book/src/pub-restricted.md [deleted file]
src/liballoc/arc.rs
src/liballoc/rc.rs
src/libcollections/fmt.rs
src/libcompiler_builtins/lib.rs
src/libcore/char.rs
src/libcore/fmt/mod.rs
src/libcore/intrinsics.rs
src/libcore/iter/iterator.rs
src/libcore/mem.rs
src/libcore/num/mod.rs
src/libcore/ptr.rs
src/libcore/raw.rs
src/libproc_macro_plugin/lib.rs
src/libproc_macro_plugin/qquote.rs [deleted file]
src/libproc_macro_plugin/quote.rs [new file with mode: 0644]
src/librustc/cfg/construct.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/lib.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/mir/mod.rs
src/librustc/traits/mod.rs
src/librustc/traits/specialize/mod.rs
src/librustc/ty/context.rs
src/librustc/ty/instance.rs [new file with mode: 0644]
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/util.rs
src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mir/gather_moves.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_borrowck/borrowck/mir/patch.rs [deleted file]
src/librustc_const_eval/diagnostics.rs
src/librustc_driver/pretty.rs
src/librustc_incremental/lib.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/expr/stmt.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/def_use.rs [deleted file]
src/librustc_mir/graphviz.rs [deleted file]
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/lib.rs
src/librustc_mir/mir_map.rs
src/librustc_mir/pretty.rs [deleted file]
src/librustc_mir/shim.rs [new file with mode: 0644]
src/librustc_mir/transform/add_call_guards.rs
src/librustc_mir/transform/copy_prop.rs
src/librustc_mir/transform/dump_mir.rs
src/librustc_mir/transform/no_landing_pads.rs
src/librustc_mir/transform/simplify.rs
src/librustc_mir/util/def_use.rs [new file with mode: 0644]
src/librustc_mir/util/elaborate_drops.rs [new file with mode: 0644]
src/librustc_mir/util/graphviz.rs [new file with mode: 0644]
src/librustc_mir/util/mod.rs [new file with mode: 0644]
src/librustc_mir/util/patch.rs [new file with mode: 0644]
src/librustc_mir/util/pretty.rs [new file with mode: 0644]
src/librustc_passes/loops.rs
src/librustc_privacy/lib.rs
src/librustc_save_analysis/Cargo.toml
src/librustc_save_analysis/csv_dumper.rs
src/librustc_save_analysis/data.rs
src/librustc_save_analysis/dump.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/external_data.rs
src/librustc_save_analysis/json_api_dumper.rs
src/librustc_save_analysis/json_dumper.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/abi.rs
src/librustc_trans/adt.rs
src/librustc_trans/attributes.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/base.rs
src/librustc_trans/callee.rs
src/librustc_trans/cleanup.rs [deleted file]
src/librustc_trans/collector.rs
src/librustc_trans/common.rs
src/librustc_trans/consts.rs
src/librustc_trans/context.rs
src/librustc_trans/debuginfo/mod.rs
src/librustc_trans/glue.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/lib.rs
src/librustc_trans/meth.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/lvalue.rs
src/librustc_trans/mir/operand.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_trans/monomorphize.rs
src/librustc_trans/partitioning.rs
src/librustc_trans/symbol_map.rs
src/librustc_trans/symbol_names_test.rs
src/librustc_trans/trans_item.rs
src/librustc_trans/tvec.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/mod.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/libstd/error.rs
src/libstd/lib.rs
src/libstd/primitive_docs.rs
src/libstd/process.rs
src/libsyntax/feature_gate.rs
src/libsyntax/tokenstream.rs
src/llvm
src/rustllvm/RustWrapper.cpp
src/rustllvm/llvm-rebuild-trigger
src/test/codegen-units/item-collection/cross-crate-generic-functions.rs
src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
src/test/codegen-units/item-collection/function-as-argument.rs
src/test/codegen-units/item-collection/generic-drop-glue.rs
src/test/codegen-units/item-collection/instantiation-through-vtable.rs
src/test/codegen-units/item-collection/items-within-generic-items.rs
src/test/codegen-units/item-collection/non-generic-drop-glue.rs
src/test/codegen-units/item-collection/non-generic-functions.rs
src/test/codegen-units/item-collection/overloaded-operators.rs
src/test/codegen-units/item-collection/static-init.rs
src/test/codegen-units/item-collection/statics-and-consts.rs
src/test/codegen-units/item-collection/trait-implementations.rs
src/test/codegen-units/item-collection/trait-method-as-argument.rs
src/test/codegen-units/item-collection/trait-method-default-impl.rs
src/test/codegen-units/item-collection/transitive-drop-glue.rs
src/test/codegen-units/item-collection/tuple-drop-glue.rs
src/test/codegen-units/item-collection/unsizing.rs
src/test/codegen-units/item-collection/unused-traits-and-generics.rs
src/test/codegen-units/partitioning/extern-drop-glue.rs
src/test/codegen-units/partitioning/extern-generic.rs
src/test/codegen-units/partitioning/local-drop-glue.rs
src/test/codegen-units/partitioning/regular-modules.rs
src/test/codegen-units/partitioning/statics.rs
src/test/codegen-units/partitioning/vtable-through-const.rs
src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs
src/test/compile-fail/catch-bad-lifetime.rs [new file with mode: 0644]
src/test/compile-fail/catch-bad-type.rs [new file with mode: 0644]
src/test/compile-fail/catch-maybe-bad-lifetime.rs [new file with mode: 0644]
src/test/compile-fail/catch-opt-init.rs [new file with mode: 0644]
src/test/compile-fail/imports/unused.rs
src/test/compile-fail/privacy/restricted/auxiliary/pub_restricted.rs
src/test/compile-fail/privacy/restricted/feature-gate.rs [deleted file]
src/test/compile-fail/privacy/restricted/lookup-ignores-private.rs
src/test/compile-fail/privacy/restricted/private-in-public.rs
src/test/compile-fail/privacy/restricted/struct-literal-field.rs
src/test/compile-fail/privacy/restricted/test.rs
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs
src/test/compile-fail/privacy/restricted/ty-params.rs
src/test/compile-fail/privacy/union-field-privacy-1.rs
src/test/compile-fail/privacy/union-field-privacy-2.rs
src/test/compile-fail/resolve-bad-visibility.rs
src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs
src/test/run-pass-fulldeps/auxiliary/hello_macro.rs
src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs
src/test/run-pass-fulldeps/macro-quote-1.rs
src/test/run-pass-fulldeps/macro-quote-empty-delims.rs [deleted file]
src/test/run-pass-fulldeps/macro-quote-test.rs [new file with mode: 0644]
src/test/run-pass/catch-expr.rs
src/test/run-pass/ifmt.rs
src/test/run-pass/issue-29948.rs
src/test/run-pass/issue-31260.rs [new file with mode: 0644]
src/test/run-pass/mir_calls_to_shims.rs [new file with mode: 0644]
src/test/rustdoc/const-doc.rs [new file with mode: 0644]
src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
src/test/ui/resolve/privacy-struct-ctor.rs
src/test/ui/resolve/privacy-struct-ctor.stderr
src/test/ui/span/pub-struct-field.rs
src/test/ui/span/pub-struct-field.stderr
src/tools/linkchecker/main.rs

index a7063bbddc5f09d52d68830f268a65abafeab194..d2e1fb868a9990b1ed81bfdda3c23f3ce78b09f9 100644 (file)
@@ -27,3 +27,6 @@
 [submodule "reference"]
        path = src/doc/reference
        url = https://github.com/rust-lang-nursery/reference.git
+[submodule "book"]
+       path = src/doc/book
+       url = https://github.com/rust-lang/book
index b34007db8ac7af314b10f246cd54147df60fef6b..a9a6fabb5b23c5ee95e864d79cef0599bf983f83 100644 (file)
@@ -27,7 +27,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
 ]
 
@@ -48,6 +48,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "arena"
 version = "0.0.0"
 
+[[package]]
+name = "atty"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "bitflags"
 version = "0.5.0"
@@ -55,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "bitflags"
-version = "0.7.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -65,11 +75,11 @@ dependencies = [
  "build_helper 0.1.0",
  "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -77,7 +87,7 @@ dependencies = [
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -94,17 +104,17 @@ version = "0.1.0"
 
 [[package]]
 name = "clap"
-version = "2.20.5"
+version = "2.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -112,7 +122,7 @@ name = "cmake"
 version = "0.1.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -130,7 +140,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -140,7 +150,7 @@ dependencies = [
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -186,7 +196,7 @@ name = "flate"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -195,7 +205,7 @@ version = "0.0.0"
 
 [[package]]
 name = "gcc"
-version = "0.3.43"
+version = "0.3.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -221,7 +231,7 @@ dependencies = [
  "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -274,7 +284,7 @@ name = "mdbook"
 version = "0.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -397,11 +407,28 @@ name = "regex-syntax"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "rls-data"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rls-span 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rls-span"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -435,7 +462,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-serialize"
-version = "0.3.22"
+version = "0.3.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -577,7 +604,7 @@ name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_bitflags 0.0.0",
 ]
 
@@ -690,8 +717,10 @@ name = "rustc_save_analysis"
 version = "0.0.0"
 dependencies = [
  "log 0.0.0",
+ "rls-data 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-span 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "serialize 0.0.0",
+ "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -751,7 +780,7 @@ version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
  "build_helper 0.1.0",
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
@@ -799,7 +828,7 @@ dependencies = [
  "collections 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -904,7 +933,7 @@ name = "toml"
 version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -940,7 +969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "vec_map"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -961,15 +990,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [metadata]
 "checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"
 "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
+"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
 "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
-"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
-"checksum clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758"
+"checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162"
+"checksum clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "74a80f603221c9cd9aa27a28f52af452850051598537bb6b359c38a7d61e5cda"
 "checksum cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "e1acc68a3f714627af38f9f5d09706a28584ba60dfe2cca68f40bf779f941b25"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
 "checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
 "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
-"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
+"checksum gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a32cd40070d7611ab76343dcb3204b2bb28c8a9450989a83a3d590248142f439"
 "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
 "checksum handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b2249f6f0dc5a3bb2b3b1a8f797dfccbc4b053344d773d654ad565e51427d335"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
@@ -987,7 +1017,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
 "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
 "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
-"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
+"checksum rls-data 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af1dfff00189fd7b78edb9af131b0de703676c04fa8126aed77fd2c586775a4d"
+"checksum rls-span 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8656f7b850ac85fb204ef94318c641bbb15a32766e12f9a589a23e4c0fbc38db"
+"checksum rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "684ce48436d6465300c9ea783b6b14c4361d6b8dcbb1375b486a69cc19e2dfb0"
 "checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f"
 "checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
@@ -1000,7 +1032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
-"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
+"checksum vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8cdc8b93bd0198ed872357fb2e667f7125646b1762f16d60b2c96350d361897"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
index ba85e81ff4fc49fadf76e6a5b2424ff5ddbdd3b4..62b7f6cb72e3baf51199d72942eb65d069a4fa89 100644 (file)
@@ -94,6 +94,13 @@ fn main() {
             cmd.arg("-Cprefer-dynamic");
         }
 
+        // Pass the `rustbuild` feature flag to crates which rustbuild is
+        // building. See the comment in bootstrap/lib.rs where this env var is
+        // set for more details.
+        if env::var_os("RUSTBUILD_UNSTABLE").is_some() {
+            cmd.arg("--cfg").arg("rustbuild");
+        }
+
         // Help the libc crate compile by assisting it in finding the MUSL
         // native libraries.
         if let Some(s) = env::var_os("MUSL_ROOT") {
index 0d962bd3b0c9324afbe89dbb41a6f5f9ef278163..40cdb9242df15b2fec93cee92f272d31e4ec5849 100644 (file)
@@ -285,6 +285,16 @@ pub fn docs(build: &Build, compiler: &Compiler) {
             continue
         }
 
+        // The nostarch directory in the book is for no starch, and so isn't guaranteed to build.
+        // we don't care if it doesn't build, so skip it.
+        use std::ffi::OsStr;
+        let path: &OsStr = p.as_ref();
+        if let Some(path) = path.to_str() {
+            if path.contains("nostarch") {
+                continue;
+            }
+        }
+
         println!("doc tests for: {}", p.display());
         markdown_test(build, compiler, &p);
     }
index db8ed579cecdb26f028739d30ca2404b0b220771..baee1ada508f2b05697a81f99a0e56a57abe04de 100644 (file)
@@ -53,6 +53,82 @@ pub fn rustbook(build: &Build, target: &str, name: &str) {
                    .arg(out));
 }
 
+/// Build the book and associated stuff.
+///
+/// We need to build:
+///
+/// * Book (first edition)
+/// * Book (second edition)
+/// * Index page
+/// * Redirect pages
+pub fn book(build: &Build, target: &str, name: &str) {
+    // build book first edition
+    rustbook(build, target, &format!("{}/first-edition", name));
+
+    // build book second edition
+    rustbook(build, target, &format!("{}/second-edition", name));
+
+    // build the index page
+    let index = format!("{}/index.md", name);
+    println!("Documenting book index ({})", target);
+    invoke_rustdoc(build, target, &index);
+
+    // build the redirect pages
+    println!("Documenting book redirect pages ({})", target);
+    for file in t!(fs::read_dir(build.src.join("src/doc/book/redirects"))) {
+        let file = t!(file);
+        let path = file.path();
+        let path = path.to_str().unwrap();
+
+        invoke_rustdoc(build, target, path);
+    }
+}
+
+fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) {
+    let out = build.doc_out(target);
+
+    let compiler = Compiler::new(0, &build.config.build);
+
+    let path = build.src.join("src/doc").join(markdown);
+
+    let rustdoc = build.rustdoc(&compiler);
+
+    let favicon = build.src.join("src/doc/favicon.inc");
+    let footer = build.src.join("src/doc/footer.inc");
+
+    let version_input = build.src.join("src/doc/version_info.html.template");
+    let version_info = out.join("version_info.html");
+
+    if !up_to_date(&version_input, &version_info) {
+        let mut info = String::new();
+        t!(t!(File::open(&version_input)).read_to_string(&mut info));
+        let info = info.replace("VERSION", &build.rust_release())
+                       .replace("SHORT_HASH", build.rust_info.sha_short().unwrap_or(""))
+                       .replace("STAMP", build.rust_info.sha().unwrap_or(""));
+        t!(t!(File::create(&version_info)).write_all(info.as_bytes()));
+    }
+
+    let mut cmd = Command::new(&rustdoc);
+
+    build.add_rustc_lib_path(&compiler, &mut cmd);
+
+    let out = out.join("book");
+
+    t!(fs::copy(build.src.join("src/doc/rust.css"), out.join("rust.css")));
+
+    cmd.arg("--html-after-content").arg(&footer)
+        .arg("--html-before-content").arg(&version_info)
+        .arg("--html-in-header").arg(&favicon)
+        .arg("--markdown-playground-url")
+        .arg("https://play.rust-lang.org/")
+        .arg("-o").arg(&out)
+        .arg(&path)
+        .arg("--markdown-css")
+        .arg("rust.css");
+
+    build.run(&mut cmd);
+}
+
 /// Generates all standalone documentation as compiled by the rustdoc in `stage`
 /// for the `target` into `out`.
 ///
index 270cb8490d9a78cc8b825191b25923e90ae925b4..26f3c063061972a96e3547f1ab0387e4f7bbafba 100644 (file)
@@ -180,7 +180,7 @@ struct Crate {
 ///
 /// These entries currently correspond to the various output directories of the
 /// build system, with each mod generating output in a different directory.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, PartialEq, Eq)]
 pub enum Mode {
     /// This cargo is going to build the standard library, placing output in the
     /// "stageN-std" directory.
@@ -491,7 +491,7 @@ fn cargo(&self,
         // For other crates, however, we know that we've already got a standard
         // library up and running, so we can use the normal compiler to compile
         // build scripts in that situation.
-        if let Mode::Libstd = mode {
+        if mode == Mode::Libstd {
             cargo.env("RUSTC_SNAPSHOT", &self.rustc)
                  .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
         } else {
@@ -499,6 +499,27 @@ fn cargo(&self,
                  .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler));
         }
 
+        // There are two invariants we try must maintain:
+        // * stable crates cannot depend on unstable crates (general Rust rule),
+        // * crates that end up in the sysroot must be unstable (rustbuild rule).
+        //
+        // In order to do enforce the latter, we pass the env var
+        // `RUSTBUILD_UNSTABLE` down the line for any crates which will end up
+        // in the sysroot. We read this in bootstrap/bin/rustc.rs and if it is
+        // set, then we pass the `rustbuild` feature to rustc when building the
+        // the crate.
+        //
+        // In turn, crates that can be used here should recognise the `rustbuild`
+        // feature and opt-in to `rustc_private`.
+        //
+        // We can't always pass `rustbuild` because crates which are outside of
+        // the comipiler, libs, and tests are stable and we don't want to make
+        // their deps unstable (since this would break the first invariant
+        // above).
+        if mode != Mode::Tool {
+            cargo.env("RUSTBUILD_UNSTABLE", "1");
+        }
+
         // Ignore incremental modes except for stage0, since we're
         // not guaranteeing correctness acros builds if the compiler
         // is changing under your feet.`
index 6b047c62d99bef2984a8836c7feacb3e918e69a0..6eb12fed5abb2d402a61cccc89b0412ecf1d3eb8 100644 (file)
@@ -581,7 +581,7 @@ fn crate_rule<'a, 'b>(build: &'a Build,
               .stage(0)
          })
          .default(build.config.docs)
-         .run(move |s| doc::rustbook(build, s.target, "book"));
+         .run(move |s| doc::book(build, s.target, "book"));
     rules.doc("doc-nomicon", "src/doc/nomicon")
          .dep(move |s| {
              s.name("tool-rustbook")
diff --git a/src/doc/book b/src/doc/book
new file mode 160000 (submodule)
index 0000000..e6d6caa
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit e6d6caab41471f7115a621029bd428a812c5260e
diff --git a/src/doc/book/src/README.md b/src/doc/book/src/README.md
deleted file mode 100644 (file)
index ade4d52..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-# The Rust Programming Language
-
-Welcome! This book will teach you about the [Rust Programming Language][rust].
-Rust is a systems programming language focused on three goals: safety, speed,
-and concurrency. It maintains these goals without having a garbage collector,
-making it a useful language for a number of use cases other languages aren’t
-good at: embedding in other languages, programs with specific space and time
-requirements, and writing low-level code, like device drivers and operating
-systems. It improves on current languages targeting this space by having a
-number of compile-time safety checks that produce no runtime overhead, while
-eliminating all data races. Rust also aims to achieve ‘zero-cost abstractions’
-even though some of these abstractions feel like those of a high-level language.
-Even then, Rust still allows precise control like a low-level language would.
-
-[rust]: https://www.rust-lang.org
-
-“The Rust Programming Language” is split into chapters. This introduction
-is the first. After this:
-
-* [Getting started][gs] - Set up your computer for Rust development.
-* [Tutorial: Guessing Game][gg] - Learn some Rust with a small project.
-* [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks.
-* [Effective Rust][er] - Higher-level concepts for writing excellent Rust code.
-* [Glossary][gl] - A reference of terms used in the book.
-* [Bibliography][bi] - Background on Rust's influences, papers about Rust.
-
-[gs]: getting-started.html
-[gg]: guessing-game.html
-[er]: effective-rust.html
-[ss]: syntax-and-semantics.html
-[gl]: glossary.html
-[bi]: bibliography.html
-
-### Contributing
-
-The source files from which this book is generated can be found on
-[GitHub][book].
-
-[book]: https://github.com/rust-lang/rust/tree/master/src/doc/book
diff --git a/src/doc/book/src/SUMMARY.md b/src/doc/book/src/SUMMARY.md
deleted file mode 100644 (file)
index c3763cd..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-# Summary
-
-[Introduction](README.md)
-
-* [Getting Started](getting-started.md)
-* [Tutorial: Guessing Game](guessing-game.md)
-* [Syntax and Semantics](syntax-and-semantics.md)
-    * [Variable Bindings](variable-bindings.md)
-    * [Functions](functions.md)
-    * [Primitive Types](primitive-types.md)
-    * [Comments](comments.md)
-    * [if](if.md)
-    * [Loops](loops.md)
-    * [Vectors](vectors.md)
-    * [Ownership](ownership.md)
-    * [References and Borrowing](references-and-borrowing.md)
-    * [Lifetimes](lifetimes.md)
-    * [Mutability](mutability.md)
-    * [Structs](structs.md)
-    * [Enums](enums.md)
-    * [Match](match.md)
-    * [Patterns](patterns.md)
-    * [Method Syntax](method-syntax.md)
-    * [Strings](strings.md)
-    * [Generics](generics.md)
-    * [Traits](traits.md)
-    * [Drop](drop.md)
-    * [if let](if-let.md)
-    * [Trait Objects](trait-objects.md)
-    * [Closures](closures.md)
-    * [Universal Function Call Syntax](ufcs.md)
-    * [Crates and Modules](crates-and-modules.md)
-    * [`const` and `static`](const-and-static.md)
-    * [Attributes](attributes.md)
-    * [`type` aliases](type-aliases.md)
-    * [Casting between types](casting-between-types.md)
-    * [Associated Types](associated-types.md)
-    * [Unsized Types](unsized-types.md)
-    * [Operators and Overloading](operators-and-overloading.md)
-    * [Deref coercions](deref-coercions.md)
-    * [Macros](macros.md)
-    * [Raw Pointers](raw-pointers.md)
-    * [`unsafe`](unsafe.md)
-* [Effective Rust](effective-rust.md)
-    * [The Stack and the Heap](the-stack-and-the-heap.md)
-    * [Testing](testing.md)
-    * [Conditional Compilation](conditional-compilation.md)
-    * [Documentation](documentation.md)
-    * [Iterators](iterators.md)
-    * [Concurrency](concurrency.md)
-    * [Error Handling](error-handling.md)
-    * [Choosing your Guarantees](choosing-your-guarantees.md)
-    * [FFI](ffi.md)
-    * [Borrow and AsRef](borrow-and-asref.md)
-    * [Release Channels](release-channels.md)
-    * [Using Rust without the standard library](using-rust-without-the-standard-library.md)
-    * [Procedural Macros (and custom derive)](procedural-macros.md)
-* [Glossary](glossary.md)
-* [Syntax Index](syntax-index.md)
-* [Bibliography](bibliography.md)
diff --git a/src/doc/book/src/associated-types.md b/src/doc/book/src/associated-types.md
deleted file mode 100644 (file)
index 4db2b9e..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-# Associated Types
-
-Associated types are a powerful part of Rust’s type system. They’re related to
-the idea of a ‘type family’, in other words, grouping multiple types together. That
-description is a bit abstract, so let’s dive right into an example. If you want
-to write a `Graph` trait, you have two types to be generic over: the node type
-and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
-this:
-
-```rust
-trait Graph<N, E> {
-    fn has_edge(&self, &N, &N) -> bool;
-    fn edges(&self, &N) -> Vec<E>;
-    // Etc.
-}
-```
-
-While this sort of works, it ends up being awkward. For example, any function
-that wants to take a `Graph` as a parameter now _also_ needs to be generic over
-the `N`ode and `E`dge types too:
-
-```rust,ignore
-fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... }
-```
-
-Our distance calculation works regardless of our `Edge` type, so the `E` stuff in
-this signature is a distraction.
-
-What we really want to say is that a certain `E`dge and `N`ode type come together
-to form each kind of `Graph`. We can do that with associated types:
-
-```rust
-trait Graph {
-    type N;
-    type E;
-
-    fn has_edge(&self, &Self::N, &Self::N) -> bool;
-    fn edges(&self, &Self::N) -> Vec<Self::E>;
-    // Etc.
-}
-```
-
-Now, our clients can be abstract over a given `Graph`:
-
-```rust,ignore
-fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> u32 { ... }
-```
-
-No need to deal with the `E`dge type here!
-
-Let’s go over all this in more detail.
-
-## Defining associated types
-
-Let’s build that `Graph` trait. Here’s the definition:
-
-```rust
-trait Graph {
-    type N;
-    type E;
-
-    fn has_edge(&self, &Self::N, &Self::N) -> bool;
-    fn edges(&self, &Self::N) -> Vec<Self::E>;
-}
-```
-
-Simple enough. Associated types use the `type` keyword, and go inside the body
-of the trait, with the functions.
-
-These type declarations work the same way as those for functions. For example,
-if we wanted our `N` type to implement `Display`, so we can print the nodes out,
-we could do this:
-
-```rust
-use std::fmt;
-
-trait Graph {
-    type N: fmt::Display;
-    type E;
-
-    fn has_edge(&self, &Self::N, &Self::N) -> bool;
-    fn edges(&self, &Self::N) -> Vec<Self::E>;
-}
-```
-
-## Implementing associated types
-
-Just like any trait, traits that use associated types use the `impl` keyword to
-provide implementations. Here’s a simple implementation of Graph:
-
-```rust
-# trait Graph {
-#     type N;
-#     type E;
-#     fn has_edge(&self, &Self::N, &Self::N) -> bool;
-#     fn edges(&self, &Self::N) -> Vec<Self::E>;
-# }
-struct Node;
-
-struct Edge;
-
-struct MyGraph;
-
-impl Graph for MyGraph {
-    type N = Node;
-    type E = Edge;
-
-    fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
-        true
-    }
-
-    fn edges(&self, n: &Node) -> Vec<Edge> {
-        Vec::new()
-    }
-}
-```
-
-This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
-gives you an idea of how to implement this kind of thing. We first need three
-`struct`s, one for the graph, one for the node, and one for the edge. If it made
-more sense to use a different type, that would work as well, we’re going to
-use `struct`s for all three here.
-
-Next is the `impl` line, which is an implementation like any other trait.
-
-From here, we use `=` to define our associated types. The name the trait uses
-goes on the left of the `=`, and the concrete type we’re `impl`ementing this
-for goes on the right. Finally, we use the concrete types in our function
-declarations.
-
-## Trait objects with associated types
-
-There’s one more bit of syntax we should talk about: trait objects. If you
-try to create a trait object from a trait with an associated type, like this:
-
-```rust,ignore
-# trait Graph {
-#     type N;
-#     type E;
-#     fn has_edge(&self, &Self::N, &Self::N) -> bool;
-#     fn edges(&self, &Self::N) -> Vec<Self::E>;
-# }
-# struct Node;
-# struct Edge;
-# struct MyGraph;
-# impl Graph for MyGraph {
-#     type N = Node;
-#     type E = Edge;
-#     fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
-#         true
-#     }
-#     fn edges(&self, n: &Node) -> Vec<Edge> {
-#         Vec::new()
-#     }
-# }
-let graph = MyGraph;
-let obj = Box::new(graph) as Box<Graph>;
-```
-
-You’ll get two errors:
-
-```text
-error: the value of the associated type `E` (from the trait `main::Graph`) must
-be specified [E0191]
-let obj = Box::new(graph) as Box<Graph>;
-          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-24:44 error: the value of the associated type `N` (from the trait
-`main::Graph`) must be specified [E0191]
-let obj = Box::new(graph) as Box<Graph>;
-          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-```
-
-We can’t create a trait object like this, because we don’t know the associated
-types. Instead, we can write this:
-
-```rust
-# trait Graph {
-#     type N;
-#     type E;
-#     fn has_edge(&self, &Self::N, &Self::N) -> bool;
-#     fn edges(&self, &Self::N) -> Vec<Self::E>;
-# }
-# struct Node;
-# struct Edge;
-# struct MyGraph;
-# impl Graph for MyGraph {
-#     type N = Node;
-#     type E = Edge;
-#     fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
-#         true
-#     }
-#     fn edges(&self, n: &Node) -> Vec<Edge> {
-#         Vec::new()
-#     }
-# }
-let graph = MyGraph;
-let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
-```
-
-The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N`
-type parameter. Same with `E=Edge`. If we didn’t provide this constraint, we
-couldn’t be sure which `impl` to match this trait object to.
diff --git a/src/doc/book/src/attributes.md b/src/doc/book/src/attributes.md
deleted file mode 100644 (file)
index 103ec39..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-# Attributes
-
-Declarations can be annotated with ‘attributes’ in Rust. They look like this:
-
-```rust
-#[test]
-# fn foo() {}
-```
-
-or like this:
-
-```rust
-# mod foo {
-#![test]
-# }
-```
-
-The difference between the two is the `!`, which changes what the attribute
-applies to:
-
-```rust,ignore
-#[foo]
-struct Foo;
-
-mod bar {
-    #![bar]
-}
-```
-
-The `#[foo]` attribute applies to the next item, which is the `struct`
-declaration. The `#![bar]` attribute applies to the item enclosing it, which is
-the `mod` declaration. Otherwise, they’re the same. Both change the meaning of
-the item they’re attached to somehow.
-
-For example, consider a function like this:
-
-```rust
-#[test]
-fn check() {
-    assert_eq!(2, 1 + 1);
-}
-```
-
-It is marked with `#[test]`. This means it’s special: when you run
-[tests][tests], this function will execute. When you compile as usual, it won’t
-even be included. This function is now a test function.
-
-[tests]: testing.html
-
-Attributes may also have additional data:
-
-```rust
-#[inline(always)]
-fn super_fast_fn() {
-# }
-```
-
-Or even keys and values:
-
-```rust
-#[cfg(target_os = "macos")]
-mod macos_only {
-# }
-```
-
-Rust attributes are used for a number of different things. There is a full list
-of attributes [in the reference][reference]. Currently, you are not allowed to
-create your own attributes, the Rust compiler defines them.
-
-[reference]: ../reference/attributes.html
diff --git a/src/doc/book/src/bibliography.md b/src/doc/book/src/bibliography.md
deleted file mode 100644 (file)
index 07b2aa9..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-# Bibliography
-
-This is a reading list of material relevant to Rust. It includes prior
-research that has - at one time or another - influenced the design of
-Rust, as well as publications about Rust.
-
-### Type system
-
-* [Region based memory management in Cyclone](http://209.68.42.137/ucsd-pages/Courses/cse227.w03/handouts/cyclone-regions.pdf)
-* [Safe manual memory management in Cyclone](http://www.cs.umd.edu/projects/PL/cyclone/scp.pdf)
-* [Typeclasses: making ad-hoc polymorphism less ad hoc](http://www.ps.uni-sb.de/courses/typen-ws99/class.ps.gz)
-* [Macros that work together](https://www.cs.utah.edu/plt/publications/jfp12-draft-fcdf.pdf)
-* [Traits: composable units of behavior](http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf)
-* [Alias burying](http://www.cs.uwm.edu/faculty/boyland/papers/unique-preprint.ps) - We tried something similar and abandoned it.
-* [External uniqueness is unique enough](http://www.cs.uu.nl/research/techreps/UU-CS-2002-048.html)
-* [Uniqueness and Reference Immutability for Safe Parallelism](https://research.microsoft.com/pubs/170528/msr-tr-2012-79.pdf)
-* [Region Based Memory Management](http://www.cs.ucla.edu/~palsberg/tba/papers/tofte-talpin-iandc97.pdf)
-
-### Concurrency
-
-* [Singularity: rethinking the software stack](https://research.microsoft.com/pubs/69431/osr2007_rethinkingsoftwarestack.pdf)
-* [Language support for fast and reliable message passing in singularity OS](https://research.microsoft.com/pubs/67482/singsharp.pdf)
-* [Scheduling multithreaded computations by work stealing](http://supertech.csail.mit.edu/papers/steal.pdf)
-* [Thread scheduling for multiprogramming multiprocessors](http://www.eecis.udel.edu/%7Ecavazos/cisc879-spring2008/papers/arora98thread.pdf)
-* [The data locality of work stealing](http://www.aladdin.cs.cmu.edu/papers/pdfs/y2000/locality_spaa00.pdf)
-* [Dynamic circular work stealing deque](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf) - The Chase/Lev deque
-* [Work-first and help-first scheduling policies for async-finish task parallelism](http://www.cs.rice.edu/%7Eyguo/pubs/PID824943.pdf) - More general than fully-strict work stealing
-* [A Java fork/join calamity](http://www.coopsoft.com/ar/CalamityArticle.html) - critique of Java's fork/join library, particularly its application of work stealing to non-strict computation
-* [Scheduling techniques for concurrent systems](http://www.stanford.edu/~ouster/cgi-bin/papers/coscheduling.pdf)
-* [Contention aware scheduling](http://www.blagodurov.net/files/a8-blagodurov.pdf)
-* [Balanced work stealing for time-sharing multicores](http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/papers/TR-12-1.pdf)
-* [Three layer cake for shared-memory programming](http://dl.acm.org/citation.cfm?id=1953616&dl=ACM&coll=DL&CFID=524387192&CFTOKEN=44362705)
-* [Non-blocking steal-half work queues](http://www.cs.bgu.ac.il/%7Ehendlerd/papers/p280-hendler.pdf)
-* [Reagents: expressing and composing fine-grained concurrency](http://www.mpi-sws.org/~turon/reagents.pdf)
-* [Algorithms for scalable synchronization of shared-memory multiprocessors](https://www.cs.rochester.edu/u/scott/papers/1991_TOCS_synch.pdf)
-* [Epoch-based reclamation](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf).
-
-### Others
-
-* [Crash-only software](https://www.usenix.org/legacy/events/hotos03/tech/full_papers/candea/candea.pdf)
-* [Composing High-Performance Memory Allocators](http://people.cs.umass.edu/~emery/pubs/berger-pldi2001.pdf)
-* [Reconsidering Custom Memory Allocation](http://people.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdf)
-
-### Papers *about* Rust
-
-* [GPU Programming in Rust: Implementing High Level Abstractions in a
-Systems Level
-Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work by Eric Holk.
-* [Parallel closures: a new twist on an old
-  idea](https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea)
-  - not exactly about Rust, but by nmatsakis
-* [Patina: A Formalization of the Rust Programming
-  Language](ftp://ftp.cs.washington.edu/tr/2015/03/UW-CSE-15-03-02.pdf). Early
-  formalization of a subset of the type system, by Eric Reed.
-* [Experience Report: Developing the Servo Web Browser Engine using
-  Rust](http://arxiv.org/abs/1505.07383). By Lars Bergstrom.
-* [Implementing a Generic Radix Trie in
-  Rust](https://michaelsproul.github.io/rust_radix_paper/rust-radix-sproul.pdf). Undergrad
-  paper by Michael Sproul.
-* [Reenix: Implementing a Unix-Like Operating System in
-  Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex
-  Light.
-* [Evaluation of performance and productivity metrics of potential
-  programming languages in the HPC environment]
-  (http://octarineparrot.com/assets/mrfloya-thesis-ba.pdf).
-  Bachelor's thesis by Florian Wilkens. Compares C, Go and Rust.
-* [Nom, a byte oriented, streaming, zero copy, parser combinators library
-  in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By
-  Geoffroy Couprie, research for VLC.
-* [Graph-Based Higher-Order Intermediate
-  Representation](http://compilers.cs.uni-saarland.de/papers/lkh15_cgo.pdf). An
-  experimental IR implemented in Impala, a Rust-like language.
-* [Code Refinement of Stencil
-  Codes](http://compilers.cs.uni-saarland.de/papers/ppl14_web.pdf). Another
-  paper using Impala.
-* [Parallelization in Rust with fork-join and
-  friends](http://publications.lib.chalmers.se/records/fulltext/219016/219016.pdf). Linus
-  Farnstrand's master's thesis.
-* [Session Types for
-  Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip
-  Munksgaard's master's thesis. Research for Servo.
-* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](http://amitlevy.com/papers/tock-plos2015.pdf)
-* [You can't spell trust without Rust](https://raw.githubusercontent.com/Gankro/thesis/master/thesis.pdf). Alexis Beingessner's master's thesis.
diff --git a/src/doc/book/src/borrow-and-asref.md b/src/doc/book/src/borrow-and-asref.md
deleted file mode 100644 (file)
index a6e3965..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-# Borrow and AsRef
-
-The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but
-different. Here’s a quick refresher on what these two traits mean.
-
-[borrow]: ../std/borrow/trait.Borrow.html
-[asref]: ../std/convert/trait.AsRef.html
-
-# Borrow
-
-The `Borrow` trait is used when you’re writing a data structure, and you want to
-use either an owned or borrowed type as synonymous for some purpose.
-
-For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`:
-
-```rust,ignore
-fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
-    where K: Borrow<Q>,
-          Q: Hash + Eq
-```
-
-[hashmap]: ../std/collections/struct.HashMap.html
-[get]: ../std/collections/struct.HashMap.html#method.get
-
-This signature is pretty complicated. The `K` parameter is what we’re interested
-in here. It refers to a parameter of the `HashMap` itself:
-
-```rust,ignore
-struct HashMap<K, V, S = RandomState> {
-```
-
-The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at
-the signature of `get()` again, we can use `get()` when the key implements
-`Borrow<Q>`. That way, we can make a `HashMap` which uses `String` keys,
-but use `&str`s when we’re searching:
-
-```rust
-use std::collections::HashMap;
-
-let mut map = HashMap::new();
-map.insert("Foo".to_string(), 42);
-
-assert_eq!(map.get("Foo"), Some(&42));
-```
-
-This is because the standard library has `impl Borrow<str> for String`.
-
-For most types, when you want to take an owned or borrowed type, a `&T` is
-enough. But one area where `Borrow` is effective is when there’s more than one
-kind of borrowed value. This is especially true of references and slices: you
-can have both an `&T` or a `&mut T`. If we wanted to accept both of these types,
-`Borrow` is up for it:
-
-```rust
-use std::borrow::Borrow;
-use std::fmt::Display;
-
-fn foo<T: Borrow<i32> + Display>(a: T) {
-    println!("a is borrowed: {}", a);
-}
-
-let mut i = 5;
-
-foo(&i);
-foo(&mut i);
-```
-
-This will print out `a is borrowed: 5` twice.
-
-# AsRef
-
-The `AsRef` trait is a conversion trait. It’s used for converting some value to
-a reference in generic code. Like this:
-
-```rust
-let s = "Hello".to_string();
-
-fn foo<T: AsRef<str>>(s: T) {
-    let slice = s.as_ref();
-}
-```
-
-# Which should I use?
-
-We can see how they’re kind of the same: they both deal with owned and borrowed
-versions of some type. However, they’re a bit different.
-
-Choose `Borrow` when you want to abstract over different kinds of borrowing, or
-when you’re building a data structure that treats owned and borrowed values in
-equivalent ways, such as hashing and comparison.
-
-Choose `AsRef` when you want to convert something to a reference directly, and
-you’re writing generic code.
diff --git a/src/doc/book/src/casting-between-types.md b/src/doc/book/src/casting-between-types.md
deleted file mode 100644 (file)
index 26cd718..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-# Casting Between Types
-
-Rust, with its focus on safety, provides two different ways of casting
-different types between each other. The first, `as`, is for safe casts.
-In contrast, `transmute` allows for arbitrary casting, and is one of the
-most dangerous features of Rust!
-
-# Coercion
-
-Coercion between types is implicit and has no syntax of its own, but can
-be spelled out with [`as`](#explicit-coercions).
-
-Coercion occurs in `let`, `const`, and `static` statements; in
-function call arguments; in field values in struct initialization; and in a
-function result.
-
-The most common case of coercion is removing mutability from a reference:
-
-* `&mut T` to `&T`
-
-An analogous conversion is to remove mutability from a
-[raw pointer](raw-pointers.html):
-
-* `*mut T` to `*const T`
-
-References can also be coerced to raw pointers:
-
-* `&T` to `*const T`
-
-* `&mut T` to `*mut T`
-
-Custom coercions may be defined using [`Deref`](deref-coercions.html).
-
-Coercion is transitive.
-
-# `as`
-
-The `as` keyword does safe casting:
-
-```rust
-let x: i32 = 5;
-
-let y = x as i64;
-```
-
-There are three major categories of safe cast: explicit coercions, casts
-between numeric types, and pointer casts.
-
-Casting is not transitive: even if `e as U1 as U2` is a valid
-expression, `e as U2` is not necessarily so (in fact it will only be valid if
-`U1` coerces to `U2`).
-
-
-## Explicit coercions
-
-A cast `e as U` is valid if `e` has type `T` and `T` *coerces* to `U`.
-
-## Numeric casts
-
-A cast `e as U` is also valid in any of the following cases:
-
-* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
-* `e` is a C-like enum (with no data attached to the variants),
-   and `U` is an integer type; *enum-cast*
-* `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast*
-* `e` has type `u8` and `U` is `char`; *u8-char-cast*
-
-For example
-
-```rust
-let one = true as u8;
-let at_sign = 64 as char;
-let two_hundred = -56i8 as u8;
-```
-
-The semantics of numeric casts are:
-
-* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op
-* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
-  truncate
-* Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
-    * zero-extend if the source is unsigned
-    * sign-extend if the source is signed
-* Casting from a float to an integer will round the float towards zero
-    * **[NOTE: currently this will cause Undefined Behavior if the rounded
-      value cannot be represented by the target integer type][float-int]**.
-      This includes Inf and NaN. This is a bug and will be fixed.
-* Casting from an integer to float will produce the floating point
-  representation of the integer, rounded if necessary (rounding strategy
-  unspecified)
-* Casting from an f32 to an f64 is perfect and lossless
-* Casting from an f64 to an f32 will produce the closest possible value
-  (rounding strategy unspecified)
-    * **[NOTE: currently this will cause Undefined Behavior if the value
-      is finite but larger or smaller than the largest or smallest finite
-      value representable by f32][float-float]**. This is a bug and will
-      be fixed.
-
-[float-int]: https://github.com/rust-lang/rust/issues/10184
-[float-float]: https://github.com/rust-lang/rust/issues/15536
-
-## Pointer casts
-
-Perhaps surprisingly, it is safe to cast [raw pointers](raw-pointers.html) to and
-from integers, and to cast between pointers to different types subject to
-some constraints. It is only unsafe to dereference the pointer:
-
-```rust
-let a = 300 as *const char; // `a` is a pointer to location 300.
-let b = a as u32;
-```
-
-`e as U` is a valid pointer cast in any of the following cases:
-
-* `e` has type `*T`, `U` has type `*U_0`, and either `U_0: Sized` or
-  `unsize_kind(T) == unsize_kind(U_0)`; a *ptr-ptr-cast*
-
-* `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast*
-
-* `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast*
-
-* `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast*
-
-* `e` is a function pointer type and `U` has type `*T`,
-  while `T: Sized`; *fptr-ptr-cast*
-
-* `e` is a function pointer type and `U` is an integer; *fptr-addr-cast*
-
-
-# `transmute`
-
-`as` only allows safe casting, and will for example reject an attempt to
-cast four bytes into a `u32`:
-
-```rust,ignore
-let a = [0u8, 0u8, 0u8, 0u8];
-
-let b = a as u32; // Four u8s makes a u32.
-```
-
-This errors with:
-
-```text
-error: non-scalar cast: `[u8; 4]` as `u32`
-let b = a as u32; // Four u8s makes a u32.
-        ^~~~~~~~
-```
-
-This is a ‘non-scalar cast’ because we have multiple values here: the four
-elements of the array. These kinds of casts are very dangerous, because they
-make assumptions about the way that multiple underlying structures are
-implemented. For this, we need something more dangerous.
-
-The `transmute` function is very simple, but very scary. It tells Rust to treat
-a value of one type as though it were another type. It does this regardless of
-the typechecking system, and completely trusts you.
-
-In our previous example, we know that an array of four `u8`s represents a `u32`
-properly, and so we want to do the cast. Using `transmute` instead of `as`,
-Rust lets us:
-
-```rust
-use std::mem;
-
-fn main() {
-    unsafe {
-        let a = [0u8, 1u8, 0u8, 0u8];
-        let b = mem::transmute::<[u8; 4], u32>(a);
-        println!("{}", b); // 256
-        // Or, more concisely:
-        let c: u32 = mem::transmute(a);
-        println!("{}", c); // 256
-    }
-}
-```
-
-We have to wrap the operation in an `unsafe` block for this to compile
-successfully. Technically, only the `mem::transmute` call itself needs to be in
-the block, but it's nice in this case to enclose everything related, so you
-know where to look. In this case, the details about `a` are also important, and
-so they're in the block. You'll see code in either style, sometimes the context
-is too far away, and wrapping all of the code in `unsafe` isn't a great idea.
-
-While `transmute` does very little checking, it will at least make sure that
-the types are the same size. This errors:
-
-```rust,ignore
-use std::mem;
-
-unsafe {
-    let a = [0u8, 0u8, 0u8, 0u8];
-
-    let b = mem::transmute::<[u8; 4], u64>(a);
-}
-```
-
-with:
-
-```text
-error: transmute called with differently sized types: [u8; 4] (32 bits) to u64
-(64 bits)
-```
-
-Other than that, you're on your own!
diff --git a/src/doc/book/src/chapter_1.md b/src/doc/book/src/chapter_1.md
deleted file mode 100644 (file)
index b743fda..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# Chapter 1
diff --git a/src/doc/book/src/choosing-your-guarantees.md b/src/doc/book/src/choosing-your-guarantees.md
deleted file mode 100644 (file)
index 89dd09e..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-# Choosing your Guarantees
-
-One important feature of Rust is that it lets us control the costs and guarantees
-of a program.
-
-There are various &ldquo;wrapper type&rdquo; abstractions in the Rust standard library which embody
-a multitude of tradeoffs between cost, ergonomics, and guarantees. Many let one choose between
-run time and compile time enforcement. This section will explain a few selected abstractions in
-detail.
-
-Before proceeding, it is highly recommended that one reads about [ownership][ownership] and
-[borrowing][borrowing] in Rust.
-
-[ownership]: ownership.html
-[borrowing]: references-and-borrowing.html
-
-# Basic pointer types
-
-## `Box<T>`
-
-[`Box<T>`][box] is an &ldquo;owned&rdquo; pointer, or a &ldquo;box&rdquo;. While it can hand
-out references to the contained data, it is the only owner of the data. In particular, consider
-the following:
-
-```rust
-let x = Box::new(1);
-let y = x;
-// `x` is no longer accessible here.
-```
-
-Here, the box was _moved_ into `y`. As `x` no longer owns it, the compiler will no longer allow the
-programmer to use `x` after this. A box can similarly be moved _out_ of a function by returning it.
-
-When a box (that hasn't been moved) goes out of scope, destructors are run. These destructors take
-care of deallocating the inner data.
-
-This is a zero-cost abstraction for dynamic allocation. If you want to allocate some memory on the
-heap and safely pass around a pointer to that memory, this is ideal. Note that you will only be
-allowed to share references to this by the regular borrowing rules, checked at compile time.
-
-[box]: ../std/boxed/struct.Box.html
-
-## `&T` and `&mut T`
-
-These are immutable and mutable references respectively. They follow the &ldquo;read-write lock&rdquo;
-pattern, such that one may either have only one mutable reference to some data, or any number of
-immutable ones, but not both. This guarantee is enforced at compile time, and has no visible cost at
-runtime. In most cases these two pointer types suffice for sharing cheap references between sections
-of code.
-
-These pointers cannot be copied in such a way that they outlive the lifetime associated with them.
-
-## `*const T` and `*mut T`
-
-These are C-like raw pointers with no lifetime or ownership attached to them. They point to
-some location in memory with no other restrictions. The only guarantee that these provide is that
-they cannot be dereferenced except in code marked `unsafe`.
-
-These are useful when building safe, low cost abstractions like `Vec<T>`, but should be avoided in
-safe code.
-
-## `Rc<T>`
-
-This is the first wrapper we will cover that has a runtime cost.
-
-[`Rc<T>`][rc] is a reference counted pointer. In other words, this lets us have multiple "owning"
-pointers to the same data, and the data will be dropped (destructors will be run) when all pointers
-are out of scope.
-
-Internally, it contains a shared &ldquo;reference count&rdquo; (also called &ldquo;refcount&rdquo;),
-which is incremented each time the `Rc` is cloned, and decremented each time one of the `Rc`s goes
-out of scope. The main responsibility of `Rc<T>` is to ensure that destructors are called for shared
-data.
-
-The internal data here is immutable, and if a cycle of references is created, the data will be
-leaked. If we want data that doesn't leak when there are cycles, we need a garbage collector.
-
-#### Guarantees
-
-The main guarantee provided here is that the data will not be destroyed until all references to it
-are out of scope.
-
-This should be used when we wish to dynamically allocate and share some data (read-only) between
-various portions of your program, where it is not certain which portion will finish using the pointer
-last. It's a viable alternative to `&T` when `&T` is either impossible to statically check for
-correctness, or creates extremely unergonomic code where the programmer does not wish to spend the
-development cost of working with.
-
-This pointer is _not_ thread safe, and Rust will not let it be sent or shared with other threads.
-This lets one avoid the cost of atomics in situations where they are unnecessary.
-
-There is a sister smart pointer to this one, `Weak<T>`. This is a non-owning, but also non-borrowed,
-smart pointer. It is also similar to `&T`, but it is not restricted in lifetime&mdash;a `Weak<T>`
-can be held on to forever. However, it is possible that an attempt to access the inner data may fail
-and return `None`, since this can outlive the owned `Rc`s. This is useful for cyclic
-data structures and other things.
-
-#### Cost
-
-As far as memory goes, `Rc<T>` is a single allocation, though it will allocate two extra words (i.e.
-two `usize` values) as compared to a regular `Box<T>` (for "strong" and "weak" refcounts).
-
-`Rc<T>` has the computational cost of incrementing/decrementing the refcount whenever it is cloned
-or goes out of scope respectively. Note that a clone will not do a deep copy, rather it will simply
-increment the inner reference count and return a copy of the `Rc<T>`.
-
-[rc]: ../std/rc/struct.Rc.html
-
-# Cell types
-
-`Cell`s provide interior mutability. In other words, they contain data which can be manipulated even
-if the type cannot be obtained in a mutable form (for example, when it is behind an `&`-ptr or
-`Rc<T>`).
-
-[The documentation for the `cell` module has a pretty good explanation for these][cell-mod].
-
-These types are _generally_ found in struct fields, but they may be found elsewhere too.
-
-## `Cell<T>`
-
-[`Cell<T>`][cell] is a type that provides zero-cost interior mutability by moving data in and
-out of the cell.
-Since the compiler knows that all the data owned by the contained value is on the stack, there's
-no worry of leaking any data behind references (or worse!) by simply replacing the data.
-
-It is still possible to violate your own invariants using this wrapper, so be careful when using it.
-If a field is wrapped in `Cell`, it's a nice indicator that the chunk of data is mutable and may not
-stay the same between the time you first read it and when you intend to use it.
-
-```rust
-use std::cell::Cell;
-
-let x = Cell::new(1);
-let y = &x;
-let z = &x;
-x.set(2);
-y.set(3);
-z.set(4);
-println!("{}", x.get());
-```
-
-Note that here we were able to mutate the same value from various immutable references.
-
-This has the same runtime cost as the following:
-
-```rust,ignore
-let mut x = 1;
-let y = &mut x;
-let z = &mut x;
-x = 2;
-*y = 3;
-*z = 4;
-println!("{}", x);
-```
-
-but it has the added benefit of actually compiling successfully.
-
-#### Guarantees
-
-This relaxes the &ldquo;no aliasing with mutability&rdquo; restriction in places where it's
-unnecessary. However, this also relaxes the guarantees that the restriction provides; so if your
-invariants depend on data stored within `Cell`, you should be careful.
-
-This is useful for mutating primitives and other types when there is no easy way of
-doing it in line with the static rules of `&` and `&mut`.
-
-`Cell` does not let you obtain interior references to the data, which makes it safe to freely
-mutate.
-
-#### Cost
-
-There is no runtime cost to using `Cell<T>`, however if you are using it to wrap larger
-structs, it might be worthwhile to instead wrap individual fields in `Cell<T>` since each write is
-otherwise a full copy of the struct.
-
-
-## `RefCell<T>`
-
-[`RefCell<T>`][refcell] also provides interior mutability, but doesn't move data in and out of the
-cell.
-
-However, it has a runtime cost. `RefCell<T>` enforces the read-write lock pattern at runtime (it's
-like a single-threaded mutex), unlike `&T`/`&mut T` which do so at compile time. This is done by the
-`borrow()` and `borrow_mut()` functions, which modify an internal reference count and return smart
-pointers which can be dereferenced immutably and mutably respectively. The refcount is restored when
-the smart pointers go out of scope. With this system, we can dynamically ensure that there are never
-any other borrows active when a mutable borrow is active. If the programmer attempts to make such a
-borrow, the thread will panic.
-
-```rust
-use std::cell::RefCell;
-
-let x = RefCell::new(vec![1,2,3,4]);
-{
-    println!("{:?}", *x.borrow())
-}
-
-{
-    let mut my_ref = x.borrow_mut();
-    my_ref.push(1);
-}
-```
-
-Similar to `Cell`, this is mainly useful for situations where it's hard or impossible to satisfy the
-borrow checker. Generally we know that such mutations won't happen in a nested form, but it's good
-to check.
-
-For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things
-simpler. For example, a lot of the maps in the `ctxt` struct in the Rust compiler internals
-are inside this wrapper. These are only modified once (during creation, which is not right after
-initialization) or a couple of times in well-separated places. However, since this struct is
-pervasively used everywhere, juggling mutable and immutable pointers would be hard (perhaps
-impossible) and probably form a soup of `&`-ptrs which would be hard to extend. On the other hand,
-the `RefCell` provides a cheap (not zero-cost) way of safely accessing these. In the future, if
-someone adds some code that attempts to modify the cell when it's already borrowed, it will cause a
-(usually deterministic) panic which can be traced back to the offending borrow.
-
-Similarly, in Servo's DOM there is a lot of mutation, most of which is local to a DOM type, but some
-of which crisscrosses the DOM and modifies various things. Using `RefCell` and `Cell` to guard all
-mutation lets us avoid worrying about mutability everywhere, and it simultaneously highlights the
-places where mutation is _actually_ happening.
-
-Note that `RefCell` should be avoided if a mostly simple solution is possible with `&` pointers.
-
-#### Guarantees
-
-`RefCell` relaxes the _static_ restrictions preventing aliased mutation, and replaces them with
-_dynamic_ ones. As such the guarantees have not changed.
-
-#### Cost
-
-`RefCell` does not allocate, but it contains an additional "borrow state"
-indicator (one word in size) along with the data.
-
-At runtime each borrow causes a modification/check of the refcount.
-
-[cell-mod]: ../std/cell/index.html
-[cell]: ../std/cell/struct.Cell.html
-[refcell]: ../std/cell/struct.RefCell.html
-
-# Synchronous types
-
-Many of the types above cannot be used in a threadsafe manner. Particularly, `Rc<T>` and
-`RefCell<T>`, which both use non-atomic reference counts (_atomic_ reference counts are those which
-can be incremented from multiple threads without causing a data race), cannot be used this way. This
-makes them cheaper to use, but we need thread safe versions of these too. They exist, in the form of
-`Arc<T>` and `Mutex<T>`/`RwLock<T>`
-
-Note that the non-threadsafe types _cannot_ be sent between threads, and this is checked at compile
-time.
-
-There are many useful wrappers for concurrent programming in the [sync][sync] module, but only the
-major ones will be covered below.
-
-[sync]: ../std/sync/index.html
-
-## `Arc<T>`
-
-[`Arc<T>`][arc] is a version of `Rc<T>` that uses an atomic reference count (hence, "Arc").
-This can be sent freely between threads.
-
-C++'s `shared_ptr` is similar to `Arc`, however in the case of C++ the inner data is always mutable.
-For semantics similar to that from C++, we should use `Arc<Mutex<T>>`, `Arc<RwLock<T>>`, or
-`Arc<UnsafeCell<T>>`[^4] (`UnsafeCell<T>` is a cell type that can be used to hold any data and has
-no runtime cost, but accessing it requires `unsafe` blocks). The last one should only be used if we
-are certain that the usage won't cause any memory unsafety. Remember that writing to a struct is not
-an atomic operation, and many functions like `vec.push()` can reallocate internally and cause unsafe
-behavior, so even monotonicity may not be enough to justify `UnsafeCell`.
-
-[^4]: `Arc<UnsafeCell<T>>` actually won't compile since `UnsafeCell<T>` isn't `Send` or `Sync`, but we can wrap it in a type and implement `Send`/`Sync` for it manually to get `Arc<Wrapper<T>>` where `Wrapper` is `struct Wrapper<T>(UnsafeCell<T>)`.
-
-#### Guarantees
-
-Like `Rc`, this provides the (thread safe) guarantee that the destructor for the internal data will
-be run when the last `Arc` goes out of scope (barring any cycles).
-
-#### Cost
-
-This has the added cost of using atomics for changing the refcount (which will happen whenever it is
-cloned or goes out of scope). When sharing data from an `Arc` in a single thread, it is preferable
-to share `&` pointers whenever possible.
-
-[arc]: ../std/sync/struct.Arc.html
-
-## `Mutex<T>` and `RwLock<T>`
-
-[`Mutex<T>`][mutex] and [`RwLock<T>`][rwlock] provide mutual-exclusion via RAII guards (guards are
-objects which maintain some state, like a lock, until their destructor is called). For both of
-these, the mutex is opaque until we call `lock()` on it, at which point the thread will block
-until a lock can be acquired, and then a guard will be returned. This guard can be used to access
-the inner data (mutably), and the lock will be released when the guard goes out of scope.
-
-```rust,ignore
-{
-    let guard = mutex.lock();
-    // `guard` dereferences mutably to the inner type.
-    *guard += 1;
-} // Lock is released when destructor runs.
-```
-
-
-`RwLock` has the added benefit of being efficient for multiple reads. It is always safe to have
-multiple readers to shared data as long as there are no writers; and `RwLock` lets readers acquire a
-"read lock". Such locks can be acquired concurrently and are kept track of via a reference count.
-Writers must obtain a "write lock" which can only be obtained when all readers have gone out of
-scope.
-
-#### Guarantees
-
-Both of these provide safe shared mutability across threads, however they are prone to deadlocks.
-Some level of additional protocol safety can be obtained via the type system.
-
-#### Costs
-
-These use internal atomic-like types to maintain the locks, which are pretty costly (they can block
-all memory reads across processors till they're done). Waiting on these locks can also be slow when
-there's a lot of concurrent access happening.
-
-[rwlock]: ../std/sync/struct.RwLock.html
-[mutex]: ../std/sync/struct.Mutex.html
-[sessions]: https://github.com/Munksgaard/rust-sessions
-
-# Composition
-
-A common gripe when reading Rust code is with types like `Rc<RefCell<Vec<T>>>` (or even more
-complicated compositions of such types). It's not always clear what the composition does, or why the
-author chose one like this (and when one should be using such a composition in one's own code)
-
-Usually, it's a case of composing together the guarantees that you need, without paying for stuff
-that is unnecessary.
-
-For example, `Rc<RefCell<T>>` is one such composition. `Rc<T>` itself can't be dereferenced mutably;
-because `Rc<T>` provides sharing and shared mutability can lead to unsafe behavior, so we put
-`RefCell<T>` inside to get dynamically verified shared mutability. Now we have shared mutable data,
-but it's shared in a way that there can only be one mutator (and no readers) or multiple readers.
-
-Now, we can take this a step further, and have `Rc<RefCell<Vec<T>>>` or `Rc<Vec<RefCell<T>>>`. These
-are both shareable, mutable vectors, but they're not the same.
-
-With the former, the `RefCell<T>` is wrapping the `Vec<T>`, so the `Vec<T>` in its entirety is
-mutable. At the same time, there can only be one mutable borrow of the whole `Vec` at a given time.
-This means that your code cannot simultaneously work on different elements of the vector from
-different `Rc` handles. However, we are able to push and pop from the `Vec<T>` at will. This is
-similar to a `&mut Vec<T>` with the borrow checking done at runtime.
-
-With the latter, the borrowing is of individual elements, but the overall vector is immutable. Thus,
-we can independently borrow separate elements, but we cannot push or pop from the vector. This is
-similar to a `&mut [T]`[^3], but, again, the borrow checking is at runtime.
-
-In concurrent programs, we have a similar situation with `Arc<Mutex<T>>`, which provides shared
-mutability and ownership.
-
-When reading code that uses these, go in step by step and look at the guarantees/costs provided.
-
-When choosing a composed type, we must do the reverse; figure out which guarantees we want, and at
-which point of the composition we need them. For example, if there is a choice between
-`Vec<RefCell<T>>` and `RefCell<Vec<T>>`, we should figure out the tradeoffs as done above and pick
-one.
-
-[^3]: `&[T]` and `&mut [T]` are _slices_; they consist of a pointer and a length and can refer to a portion of a vector or array. `&mut [T]` can have its elements mutated, however its length cannot be touched.
diff --git a/src/doc/book/src/closures.md b/src/doc/book/src/closures.md
deleted file mode 100644 (file)
index 5426ed0..0000000
+++ /dev/null
@@ -1,552 +0,0 @@
-# Closures
-
-Sometimes it is useful to wrap up a function and _free variables_ for better
-clarity and reuse. The free variables that can be used come from the
-enclosing scope and are ‘closed over’ when used in the function. From this, we
-get the name ‘closures’ and Rust provides a really great implementation of
-them, as we’ll see.
-
-# Syntax
-
-Closures look like this:
-
-```rust
-let plus_one = |x: i32| x + 1;
-
-assert_eq!(2, plus_one(1));
-```
-
-We create a binding, `plus_one`, and assign it to a closure. The closure’s
-arguments go between the pipes (`|`), and the body is an expression, in this
-case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line
-closures too:
-
-```rust
-let plus_two = |x| {
-    let mut result: i32 = x;
-
-    result += 1;
-    result += 1;
-
-    result
-};
-
-assert_eq!(4, plus_two(2));
-```
-
-You’ll notice a few things about closures that are a bit different from regular
-named functions defined with `fn`. The first is that we did not need to
-annotate the types of arguments the closure takes or the values it returns. We
-can:
-
-```rust
-let plus_one = |x: i32| -> i32 { x + 1 };
-
-assert_eq!(2, plus_one(1));
-```
-
-But we don’t have to. Why is this? Basically, it was chosen for ergonomic
-reasons. While specifying the full type for named functions is helpful with
-things like documentation and type inference, the full type signatures of
-closures are rarely documented since they’re anonymous, and they don’t cause
-the kinds of error-at-a-distance problems that inferring named function types
-can.
-
-The second is that the syntax is similar, but a bit different. I’ve added
-spaces here for easier comparison:
-
-```rust
-fn  plus_one_v1   (x: i32) -> i32 { x + 1 }
-let plus_one_v2 = |x: i32| -> i32 { x + 1 };
-let plus_one_v3 = |x: i32|          x + 1  ;
-```
-
-Small differences, but they’re similar.
-
-# Closures and their environment
-
-The environment for a closure can include bindings from its enclosing scope in
-addition to parameters and local bindings. It looks like this:
-
-```rust
-let num = 5;
-let plus_num = |x: i32| x + num;
-
-assert_eq!(10, plus_num(5));
-```
-
-This closure, `plus_num`, refers to a `let` binding in its scope: `num`. More
-specifically, it borrows the binding. If we do something that would conflict
-with that binding, we get an error. Like this one:
-
-```rust,ignore
-let mut num = 5;
-let plus_num = |x: i32| x + num;
-
-let y = &mut num;
-```
-
-Which errors with:
-
-```text
-error: cannot borrow `num` as mutable because it is also borrowed as immutable
-    let y = &mut num;
-                 ^~~
-note: previous borrow of `num` occurs here due to use in closure; the immutable
-  borrow prevents subsequent moves or mutable borrows of `num` until the borrow
-  ends
-    let plus_num = |x| x + num;
-                   ^~~~~~~~~~~
-note: previous borrow ends here
-fn main() {
-    let mut num = 5;
-    let plus_num = |x| x + num;
-
-    let y = &mut num;
-}
-^
-```
-
-A verbose yet helpful error message! As it says, we can’t take a mutable borrow
-on `num` because the closure is already borrowing it. If we let the closure go
-out of scope, we can:
-
-```rust
-let mut num = 5;
-{
-    let plus_num = |x: i32| x + num;
-
-} // `plus_num` goes out of scope; borrow of `num` ends.
-
-let y = &mut num;
-```
-
-If your closure requires it, however, Rust will take ownership and move
-the environment instead. This doesn’t work:
-
-```rust,ignore
-let nums = vec![1, 2, 3];
-
-let takes_nums = || nums;
-
-println!("{:?}", nums);
-```
-
-We get this error:
-
-```text
-note: `nums` moved into closure environment here because it has type
-  `[closure(()) -> collections::vec::Vec<i32>]`, which is non-copyable
-let takes_nums = || nums;
-                 ^~~~~~~
-```
-
-`Vec<T>` has ownership over its contents, and therefore, when we refer to it
-in our closure, we have to take ownership of `nums`. It’s the same as if we’d
-passed `nums` to a function that took ownership of it.
-
-## `move` closures
-
-We can force our closure to take ownership of its environment with the `move`
-keyword:
-
-```rust
-let num = 5;
-
-let owns_num = move |x: i32| x + num;
-```
-
-Now, even though the keyword is `move`, the variables follow normal move semantics.
-In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy
-of `num`. So what’s the difference?
-
-```rust
-let mut num = 5;
-
-{
-    let mut add_num = |x: i32| num += x;
-
-    add_num(5);
-}
-
-assert_eq!(10, num);
-```
-
-So in this case, our closure took a mutable reference to `num`, and then when
-we called `add_num`, it mutated the underlying value, as we’d expect. We also
-needed to declare `add_num` as `mut` too, because we’re mutating its
-environment.
-
-If we change to a `move` closure, it’s different:
-
-```rust
-let mut num = 5;
-
-{
-    let mut add_num = move |x: i32| num += x;
-
-    add_num(5);
-}
-
-assert_eq!(5, num);
-```
-
-We only get `5`. Rather than taking a mutable borrow out on our `num`, we took
-ownership of a copy.
-
-Another way to think about `move` closures: they give a closure its own stack
-frame.  Without `move`, a closure may be tied to the stack frame that created
-it, while a `move` closure is self-contained. This means that you cannot
-generally return a non-`move` closure from a function, for example.
-
-But before we talk about taking and returning closures, we should talk some
-more about the way that closures are implemented. As a systems language, Rust
-gives you tons of control over what your code does, and closures are no
-different.
-
-# Closure implementation
-
-Rust’s implementation of closures is a bit different than other languages. They
-are effectively syntax sugar for traits. You’ll want to make sure to have read
-the [traits][traits] section before this one, as well as the section on [trait
-objects][trait-objects].
-
-[traits]: traits.html
-[trait-objects]: trait-objects.html
-
-Got all that? Good.
-
-The key to understanding how closures work under the hood is something a bit
-strange: Using `()` to call a function, like `foo()`, is an overloadable
-operator. From this, everything else clicks into place. In Rust, we use the
-trait system to overload operators. Calling functions is no different. We have
-three separate traits to overload with:
-
-```rust
-# #![feature(unboxed_closures)]
-# mod foo {
-pub trait Fn<Args> : FnMut<Args> {
-    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
-}
-
-pub trait FnMut<Args> : FnOnce<Args> {
-    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
-}
-
-pub trait FnOnce<Args> {
-    type Output;
-
-    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-}
-# }
-```
-
-You’ll notice a few differences between these traits, but a big one is `self`:
-`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This
-covers all three kinds of `self` via the usual method call syntax. But we’ve
-split them up into three traits, rather than having a single one. This gives us
-a large amount of control over what kind of closures we can take.
-
-The `|| {}` syntax for closures is sugar for these three traits. Rust will
-generate a struct for the environment, `impl` the appropriate trait, and then
-use it.
-
-# Taking closures as arguments
-
-Now that we know that closures are traits, we already know how to accept and
-return closures: the same as any other trait!
-
-This also means that we can choose static vs dynamic dispatch as well. First,
-let’s write a function which takes something callable, calls it, and returns
-the result:
-
-```rust
-fn call_with_one<F>(some_closure: F) -> i32
-    where F: Fn(i32) -> i32 {
-
-    some_closure(1)
-}
-
-let answer = call_with_one(|x| x + 2);
-
-assert_eq!(3, answer);
-```
-
-We pass our closure, `|x| x + 2`, to `call_with_one`. It does what it
-suggests: it calls the closure, giving it `1` as an argument.
-
-Let’s examine the signature of `call_with_one` in more depth:
-
-```rust
-fn call_with_one<F>(some_closure: F) -> i32
-#    where F: Fn(i32) -> i32 {
-#    some_closure(1) }
-```
-
-We take one parameter, and it has the type `F`. We also return an `i32`. This part
-isn’t interesting. The next part is:
-
-```rust
-# fn call_with_one<F>(some_closure: F) -> i32
-    where F: Fn(i32) -> i32 {
-#   some_closure(1) }
-```
-
-Because `Fn` is a trait, we can use it as a bound for our generic type. In
-this case, our closure takes an `i32` as an argument and returns an `i32`, and
-so the generic bound we use is `Fn(i32) -> i32`.
-
-There’s one other key point here: because we’re bounding a generic with a
-trait, this will get monomorphized, and therefore, we’ll be doing static
-dispatch into the closure. That’s pretty neat. In many languages, closures are
-inherently heap allocated, and will always involve dynamic dispatch. In Rust,
-we can stack allocate our closure environment, and statically dispatch the
-call. This happens quite often with iterators and their adapters, which often
-take closures as arguments.
-
-Of course, if we want dynamic dispatch, we can get that too. A trait object
-handles this case, as usual:
-
-```rust
-fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
-    some_closure(1)
-}
-
-let answer = call_with_one(&|x| x + 2);
-
-assert_eq!(3, answer);
-```
-
-Now we take a trait object, a `&Fn`. And we have to make a reference
-to our closure when we pass it to `call_with_one`, so we use `&||`.
-
-A quick note about closures that use explicit lifetimes. Sometimes you might have a closure
-that takes a reference like so:
-
-```rust
-fn call_with_ref<F>(some_closure:F) -> i32
-    where F: Fn(&i32) -> i32 {
-
-    let value = 0;
-    some_closure(&value)
-}
-```
-
-Normally you can specify the lifetime of the parameter to our closure. We
-could annotate it on the function declaration:
-
-```rust,ignore
-fn call_with_ref<'a, F>(some_closure:F) -> i32
-    where F: Fn(&'a i32) -> i32 {
-```
-
-However, this presents a problem in our case. When a function has an explicit
-lifetime parameter, that lifetime must be at least as long as the *entire*
-call to that function.  The borrow checker will complain that `value` doesn't
-live long enough, because it is only in scope after its declaration inside the
-function body.
-
-What we need is a closure that can borrow its argument only for its own
-invocation scope, not for the outer function's scope.  In order to say that,
-we can use Higher-Ranked Trait Bounds with the `for<...>` syntax:
-
-```ignore
-fn call_with_ref<F>(some_closure:F) -> i32
-    where F: for<'a> Fn(&'a i32) -> i32 {
-```
-
-This lets the Rust compiler find the minimum lifetime to invoke our closure and
-satisfy the borrow checker's rules. Our function then compiles and executes as we
-expect.
-
-```rust
-fn call_with_ref<F>(some_closure:F) -> i32
-    where F: for<'a> Fn(&'a i32) -> i32 {
-
-    let value = 0;
-    some_closure(&value)
-}
-```
-
-# Function pointers and closures
-
-A function pointer is kind of like a closure that has no environment. As such,
-you can pass a function pointer to any function expecting a closure argument,
-and it will work:
-
-```rust
-fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
-    some_closure(1)
-}
-
-fn add_one(i: i32) -> i32 {
-    i + 1
-}
-
-let f = add_one;
-
-let answer = call_with_one(&f);
-
-assert_eq!(2, answer);
-```
-
-In this example, we don’t strictly need the intermediate variable `f`,
-the name of the function works just fine too:
-
-```rust,ignore
-let answer = call_with_one(&add_one);
-```
-
-# Returning closures
-
-It’s very common for functional-style code to return closures in various
-situations. If you try to return a closure, you may run into an error. At
-first, it may seem strange, but we’ll figure it out. Here’s how you’d probably
-try to return a closure from a function:
-
-```rust,ignore
-fn factory() -> (Fn(i32) -> i32) {
-    let num = 5;
-
-    |x| x + num
-}
-
-let f = factory();
-
-let answer = f(1);
-assert_eq!(6, answer);
-```
-
-This gives us these long, related errors:
-
-```text
-error: the trait bound `core::ops::Fn(i32) -> i32 : core::marker::Sized` is not satisfied [E0277]
-fn factory() -> (Fn(i32) -> i32) {
-                ^~~~~~~~~~~~~~~~
-note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time
-fn factory() -> (Fn(i32) -> i32) {
-                ^~~~~~~~~~~~~~~~
-error: the trait bound `core::ops::Fn(i32) -> i32 : core::marker::Sized` is not satisfied [E0277]
-let f = factory();
-    ^
-note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time
-let f = factory();
-    ^
-```
-
-In order to return something from a function, Rust needs to know what
-size the return type is. But since `Fn` is a trait, it could be various
-things of various sizes: many different types can implement `Fn`. An easy
-way to give something a size is to take a reference to it, as references
-have a known size. So we’d write this:
-
-```rust,ignore
-fn factory() -> &(Fn(i32) -> i32) {
-    let num = 5;
-
-    |x| x + num
-}
-
-let f = factory();
-
-let answer = f(1);
-assert_eq!(6, answer);
-```
-
-But we get another error:
-
-```text
-error: missing lifetime specifier [E0106]
-fn factory() -> &(Fn(i32) -> i32) {
-                ^~~~~~~~~~~~~~~~~
-```
-
-Right. Because we have a reference, we need to give it a lifetime. But
-our `factory()` function takes no arguments, so
-[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what
-choices do we have? Try `'static`:
-
-```rust,ignore
-fn factory() -> &'static (Fn(i32) -> i32) {
-    let num = 5;
-
-    |x| x + num
-}
-
-let f = factory();
-
-let answer = f(1);
-assert_eq!(6, answer);
-```
-
-But we get another error:
-
-```text
-error: mismatched types:
- expected `&'static core::ops::Fn(i32) -> i32`,
-    found `[closure@<anon>:7:9: 7:20]`
-(expected &-ptr,
-    found closure) [E0308]
-         |x| x + num
-         ^~~~~~~~~~~
-
-```
-
-This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`,
-we have a `[closure@<anon>:7:9: 7:20]`. Wait, what?
-
-Because each closure generates its own environment `struct` and implementation
-of `Fn` and friends, these types are anonymous. They exist solely for
-this closure. So Rust shows them as `closure@<anon>`, rather than some
-autogenerated name.
-
-The error also points out that the return type is expected to be a reference,
-but what we are trying to return is not. Further, we cannot directly assign a
-`'static` lifetime to an object. So we'll take a different approach and return
-a ‘trait object’ by `Box`ing up the `Fn`. This _almost_ works:
-
-```rust,ignore
-fn factory() -> Box<Fn(i32) -> i32> {
-    let num = 5;
-
-    Box::new(|x| x + num)
-}
-
-let f = factory();
-
-let answer = f(1);
-assert_eq!(6, answer);
-```
-
-There’s just one last problem:
-
-```text
-error: closure may outlive the current function, but it borrows `num`,
-which is owned by the current function [E0373]
-Box::new(|x| x + num)
-         ^~~~~~~~~~~
-```
-
-Well, as we discussed before, closures borrow their environment. And in this
-case, our environment is based on a stack-allocated `5`, the `num` variable
-binding. So the borrow has a lifetime of the stack frame. So if we returned
-this closure, the function call would be over, the stack frame would go away,
-and our closure is capturing an environment of garbage memory! With one last
-fix, we can make this work:
-
-```rust
-fn factory() -> Box<Fn(i32) -> i32> {
-    let num = 5;
-
-    Box::new(move |x| x + num)
-}
-
-let f = factory();
-
-let answer = f(1);
-assert_eq!(6, answer);
-```
-
-By making the inner closure a `move Fn`, we create a new stack frame for our
-closure. By `Box`ing it up, we’ve given it a known size, allowing it to
-escape our stack frame.
diff --git a/src/doc/book/src/comments.md b/src/doc/book/src/comments.md
deleted file mode 100644 (file)
index 0e68ab2..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# Comments
-
-Now that we have some functions, it’s a good idea to learn about comments.
-Comments are notes that you leave to other programmers to help explain things
-about your code. The compiler mostly ignores them.
-
-Rust has two kinds of comments that you should care about: *line comments*
-and *doc comments*.
-
-```rust
-// Line comments are anything after ‘//’ and extend to the end of the line.
-
-let x = 5; // This is also a line comment.
-
-// If you have a long explanation for something, you can put line comments next
-// to each other. Put a space between the // and your comment so that it’s
-// more readable.
-```
-
-The other kind of comment is a doc comment. Doc comments use `///` instead of
-`//`, and support Markdown notation inside:
-
-```rust
-/// Adds one to the number given.
-///
-/// # Examples
-///
-/// ```
-/// let five = 5;
-///
-/// assert_eq!(6, add_one(5));
-/// # fn add_one(x: i32) -> i32 {
-/// #     x + 1
-/// # }
-/// ```
-fn add_one(x: i32) -> i32 {
-    x + 1
-}
-```
-
-There is another style of doc comment, `//!`, to comment containing items (e.g.
-crates, modules or functions), instead of the items following it. Commonly used
-inside crates root (lib.rs) or modules root (mod.rs):
-
-```
-//! # The Rust Standard Library
-//!
-//! The Rust Standard Library provides the essential runtime
-//! functionality for building portable Rust software.
-```
-
-When writing doc comments, providing some examples of usage is very, very
-helpful. You’ll notice we’ve used a new macro here: `assert_eq!`. This compares
-two values, and `panic!`s if they’re not equal to each other. It’s very helpful
-in documentation. There’s another macro, `assert!`, which `panic!`s if the
-value passed to it is `false`.
-
-You can use the [`rustdoc`](documentation.html) tool to generate HTML documentation
-from these doc comments, and also to run the code examples as tests!
diff --git a/src/doc/book/src/compiler-plugins.md b/src/doc/book/src/compiler-plugins.md
deleted file mode 100644 (file)
index c05d808..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-# Compiler Plugins
-
-## Introduction
-
-`rustc` can load compiler plugins, which are user-provided libraries that
-extend the compiler's behavior with new syntax extensions, lint checks, etc.
-
-A plugin is a dynamic library crate with a designated *registrar* function that
-registers extensions with `rustc`. Other crates can load these extensions using
-the crate attribute `#![plugin(...)]`.  See the
-`rustc_plugin` documentation for more about the
-mechanics of defining and loading a plugin.
-
-If present, arguments passed as `#![plugin(foo(... args ...))]` are not
-interpreted by rustc itself.  They are provided to the plugin through the
-`Registry`'s `args` method.
-
-In the vast majority of cases, a plugin should *only* be used through
-`#![plugin]` and not through an `extern crate` item.  Linking a plugin would
-pull in all of libsyntax and librustc as dependencies of your crate.  This is
-generally unwanted unless you are building another plugin.  The
-`plugin_as_library` lint checks these guidelines.
-
-The usual practice is to put compiler plugins in their own crate, separate from
-any `macro_rules!` macros or ordinary Rust code meant to be used by consumers
-of a library.
-
-# Syntax extensions
-
-Plugins can extend Rust's syntax in various ways. One kind of syntax extension
-is the procedural macro. These are invoked the same way as [ordinary
-macros](macros.html), but the expansion is performed by arbitrary Rust
-code that manipulates syntax trees at
-compile time.
-
-Let's write a plugin
-[`roman_numerals.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs)
-that implements Roman numeral integer literals.
-
-```rust,ignore
-#![crate_type="dylib"]
-#![feature(plugin_registrar, rustc_private)]
-
-extern crate syntax;
-extern crate rustc;
-extern crate rustc_plugin;
-
-use syntax::parse::token;
-use syntax::tokenstream::TokenTree;
-use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
-use syntax::ext::build::AstBuilder;  // A trait for expr_usize.
-use syntax::ext::quote::rt::Span;
-use rustc_plugin::Registry;
-
-fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
-        -> Box<MacResult + 'static> {
-
-    static NUMERALS: &'static [(&'static str, usize)] = &[
-        ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
-        ("C",  100), ("XC",  90), ("L",  50), ("XL",  40),
-        ("X",   10), ("IX",   9), ("V",   5), ("IV",   4),
-        ("I",    1)];
-
-    if args.len() != 1 {
-        cx.span_err(
-            sp,
-            &format!("argument should be a single identifier, but got {} arguments", args.len()));
-        return DummyResult::any(sp);
-    }
-
-    let text = match args[0] {
-        TokenTree::Token(_, token::Ident(s)) => s.to_string(),
-        _ => {
-            cx.span_err(sp, "argument should be a single identifier");
-            return DummyResult::any(sp);
-        }
-    };
-
-    let mut text = &*text;
-    let mut total = 0;
-    while !text.is_empty() {
-        match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
-            Some(&(rn, val)) => {
-                total += val;
-                text = &text[rn.len()..];
-            }
-            None => {
-                cx.span_err(sp, "invalid Roman numeral");
-                return DummyResult::any(sp);
-            }
-        }
-    }
-
-    MacEager::expr(cx.expr_usize(sp, total))
-}
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_macro("rn", expand_rn);
-}
-```
-
-Then we can use `rn!()` like any other macro:
-
-```rust,ignore
-#![feature(plugin)]
-#![plugin(roman_numerals)]
-
-fn main() {
-    assert_eq!(rn!(MMXV), 2015);
-}
-```
-
-The advantages over a simple `fn(&str) -> u32` are:
-
-* The (arbitrarily complex) conversion is done at compile time.
-* Input validation is also performed at compile time.
-* It can be extended to allow use in patterns, which effectively gives
-  a way to define new literal syntax for any data type.
-
-In addition to procedural macros, you can define new
-[`derive`](../reference/attributes.html#derive)-like attributes and other kinds of
-extensions.  See `Registry::register_syntax_extension` and the `SyntaxExtension`
-enum.  For a more involved macro example, see
-[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs).
-
-
-## Tips and tricks
-
-Some of the [macro debugging tips](macros.html#debugging-macro-code) are applicable.
-
-You can use `syntax::parse` to turn token trees into
-higher-level syntax elements like expressions:
-
-```rust,ignore
-fn expand_foo(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
-        -> Box<MacResult+'static> {
-
-    let mut parser = cx.new_parser_from_tts(args);
-
-    let expr: P<Expr> = parser.parse_expr();
-```
-
-Looking through [`libsyntax` parser
-code](https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/parser.rs)
-will give you a feel for how the parsing infrastructure works.
-
-Keep the `Span`s of everything you parse, for better error reporting. You can
-wrap `Spanned` around your custom data structures.
-
-Calling `ExtCtxt::span_fatal` will immediately abort compilation. It's better to
-instead call `ExtCtxt::span_err` and return `DummyResult` so that the compiler
-can continue and find further errors.
-
-To print syntax fragments for debugging, you can use `span_note` together with
-`syntax::print::pprust::*_to_string`.
-
-The example above produced an integer literal using `AstBuilder::expr_usize`.
-As an alternative to the `AstBuilder` trait, `libsyntax` provides a set of
-quasiquote macros. They are undocumented and very rough around the edges.
-However, the implementation may be a good starting point for an improved
-quasiquote as an ordinary plugin library.
-
-
-# Lint plugins
-
-Plugins can extend [Rust's lint
-infrastructure](../reference/attributes.html#lint-check-attributes) with
-additional checks for code style, safety, etc. Now let's write a plugin
-[`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs)
-that warns about any item named `lintme`.
-
-```rust,ignore
-#![feature(plugin_registrar)]
-#![feature(box_syntax, rustc_private)]
-
-extern crate syntax;
-
-// Load rustc as a plugin to get macros
-#[macro_use]
-extern crate rustc;
-extern crate rustc_plugin;
-
-use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
-                  EarlyLintPassObject, LintArray};
-use rustc_plugin::Registry;
-use syntax::ast;
-
-declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
-
-struct Pass;
-
-impl LintPass for Pass {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT)
-    }
-}
-
-impl EarlyLintPass for Pass {
-    fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
-        if it.ident.name.as_str() == "lintme" {
-            cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
-        }
-    }
-}
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_early_lint_pass(box Pass as EarlyLintPassObject);
-}
-```
-
-Then code like
-
-```rust,ignore
-#![plugin(lint_plugin_test)]
-
-fn lintme() { }
-```
-
-will produce a compiler warning:
-
-```txt
-foo.rs:4:1: 4:16 warning: item is named 'lintme', #[warn(test_lint)] on by default
-foo.rs:4 fn lintme() { }
-         ^~~~~~~~~~~~~~~
-```
-
-The components of a lint plugin are:
-
-* one or more `declare_lint!` invocations, which define static `Lint` structs;
-
-* a struct holding any state needed by the lint pass (here, none);
-
-* a `LintPass`
-  implementation defining how to check each syntax element. A single
-  `LintPass` may call `span_lint` for several different `Lint`s, but should
-  register them all through the `get_lints` method.
-
-Lint passes are syntax traversals, but they run at a late stage of compilation
-where type information is available. `rustc`'s [built-in
-lints](https://github.com/rust-lang/rust/blob/master/src/librustc/lint/builtin.rs)
-mostly use the same infrastructure as lint plugins, and provide examples of how
-to access type information.
-
-Lints defined by plugins are controlled by the usual [attributes and compiler
-flags](../reference/attributes.html#lint-check-attributes), e.g.
-`#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the
-first argument to `declare_lint!`, with appropriate case and punctuation
-conversion.
-
-You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`,
-including those provided by plugins loaded by `foo.rs`.
diff --git a/src/doc/book/src/concurrency.md b/src/doc/book/src/concurrency.md
deleted file mode 100644 (file)
index afed379..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-# Concurrency
-
-Concurrency and parallelism are incredibly important topics in computer
-science, and are also a hot topic in industry today. Computers are gaining more
-and more cores, yet many programmers aren't prepared to fully utilize them.
-
-Rust's memory safety features also apply to its concurrency story. Even
-concurrent Rust programs must be memory safe, having no data races. Rust's type
-system is up to the task, and gives you powerful ways to reason about
-concurrent code at compile time.
-
-Before we talk about the concurrency features that come with Rust, it's important
-to understand something: Rust is low-level enough that the vast majority of
-this is provided by the standard library, not by the language. This means that
-if you don't like some aspect of the way Rust handles concurrency, you can
-implement an alternative way of doing things.
-[mio](https://github.com/carllerche/mio) is a real-world example of this
-principle in action.
-
-## Background: `Send` and `Sync`
-
-Concurrency is difficult to reason about. In Rust, we have a strong, static
-type system to help us reason about our code. As such, Rust gives us two traits
-to help us make sense of code that can possibly be concurrent.
-
-### `Send`
-
-The first trait we're going to talk about is
-[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it
-indicates that something of this type is able to have ownership transferred
-safely between threads.
-
-This is important to enforce certain restrictions. For example, if we have a
-channel connecting two threads, we would want to be able to send some data
-down the channel and to the other thread. Therefore, we'd ensure that `Send` was
-implemented for that type.
-
-In the opposite way, if we were wrapping a library with [FFI][ffi] that isn't
-thread-safe, we wouldn't want to implement `Send`, and so the compiler will help
-us enforce that it can't leave the current thread.
-
-[ffi]: ffi.html
-
-### `Sync`
-
-The second of these traits is called [`Sync`](../std/marker/trait.Sync.html).
-When a type `T` implements `Sync`, it indicates that something
-of this type has no possibility of introducing memory unsafety when used from
-multiple threads concurrently through shared references. This implies that
-types which don't have [interior mutability](mutability.html) are inherently
-`Sync`, which includes simple primitive types (like `u8`) and aggregate types
-containing them.
-
-For sharing references across threads, Rust provides a wrapper type called
-`Arc<T>`. `Arc<T>` implements `Send` and `Sync` if and only if `T` implements
-both `Send` and `Sync`. For example, an object of type `Arc<RefCell<U>>` cannot
-be transferred across threads because
-[`RefCell`](choosing-your-guarantees.html#refcellt) does not implement
-`Sync`, consequently `Arc<RefCell<U>>` would not implement `Send`.
-
-These two traits allow you to use the type system to make strong guarantees
-about the properties of your code under concurrency. Before we demonstrate
-why, we need to learn how to create a concurrent Rust program in the first
-place!
-
-## Threads
-
-Rust's standard library provides a library for threads, which allow you to
-run Rust code in parallel. Here's a basic example of using `std::thread`:
-
-```rust
-use std::thread;
-
-fn main() {
-    thread::spawn(|| {
-        println!("Hello from a thread!");
-    });
-}
-```
-
-The `thread::spawn()` method accepts a [closure](closures.html), which is executed in a
-new thread. It returns a handle to the thread, that can be used to
-wait for the child thread to finish and extract its result:
-
-```rust
-use std::thread;
-
-fn main() {
-    let handle = thread::spawn(|| {
-        "Hello from a thread!"
-    });
-
-    println!("{}", handle.join().unwrap());
-}
-```
-
-As closures can capture variables from their environment, we can also try to
-bring some data into the other thread:
-
-```rust,ignore
-use std::thread;
-
-fn main() {
-    let x = 1;
-    thread::spawn(|| {
-        println!("x is {}", x);
-    });
-}
-```
-
-However, this gives us an error:
-
-```text
-5:19: 7:6 error: closure may outlive the current function, but it
-                 borrows `x`, which is owned by the current function
-...
-5:19: 7:6 help: to force the closure to take ownership of `x` (and any other referenced variables),
-          use the `move` keyword, as shown:
-      thread::spawn(move || {
-          println!("x is {}", x);
-      });
-```
-
-This is because by default closures capture variables by reference, and thus the
-closure only captures a _reference to `x`_. This is a problem, because the
-thread may outlive the scope of `x`, leading to a dangling pointer.
-
-To fix this, we use a `move` closure as mentioned in the error message. `move`
-closures are explained in depth [here](closures.html#move-closures); basically
-they move variables from their environment into themselves.
-
-```rust
-use std::thread;
-
-fn main() {
-    let x = 1;
-    thread::spawn(move || {
-        println!("x is {}", x);
-    });
-}
-```
-
-Many languages have the ability to execute threads, but it's wildly unsafe.
-There are entire books about how to prevent errors that occur from shared
-mutable state. Rust helps out with its type system here as well, by preventing
-data races at compile time. Let's talk about how you actually share things
-between threads.
-
-## Safe Shared Mutable State
-
-Due to Rust's type system, we have a concept that sounds like a lie: "safe
-shared mutable state." Many programmers agree that shared mutable state is
-very, very bad.
-
-Someone once said this:
-
-> Shared mutable state is the root of all evil. Most languages attempt to deal
-> with this problem through the 'mutable' part, but Rust deals with it by
-> solving the 'shared' part.
-
-The same [ownership system](ownership.html) that helps prevent using pointers
-incorrectly also helps rule out data races, one of the worst kinds of
-concurrency bugs.
-
-As an example, here is a Rust program that would have a data race in many
-languages. It will not compile:
-
-```rust,ignore
-use std::thread;
-use std::time::Duration;
-
-fn main() {
-    let mut data = vec![1, 2, 3];
-
-    for i in 0..3 {
-        thread::spawn(move || {
-            data[0] += i;
-        });
-    }
-
-    thread::sleep(Duration::from_millis(50));
-}
-```
-
-This gives us an error:
-
-```text
-8:17 error: capture of moved value: `data`
-        data[0] += i;
-        ^~~~
-```
-
-Rust knows this wouldn't be safe! If we had a reference to `data` in each
-thread, and the thread takes ownership of the reference, we'd have three owners!
-`data` gets moved out of `main` in the first call to `spawn()`, so subsequent
-calls in the loop cannot use this variable.
-
-So, we need some type that lets us have more than one owning reference to a
-value. Usually, we'd use `Rc<T>` for this, which is a reference counted type
-that provides shared ownership. It has some runtime bookkeeping that keeps track
-of the number of references to it, hence the "reference count" part of its name.
-
-Calling `clone()` on an `Rc<T>` will return a new owned reference and bump the
-internal reference count. We create one of these for each thread:
-
-
-```rust,ignore
-use std::thread;
-use std::time::Duration;
-use std::rc::Rc;
-
-fn main() {
-    let mut data = Rc::new(vec![1, 2, 3]);
-
-    for i in 0..3 {
-        // Create a new owned reference:
-        let data_ref = data.clone();
-
-        // Use it in a thread:
-        thread::spawn(move || {
-            data_ref[0] += i;
-        });
-    }
-
-    thread::sleep(Duration::from_millis(50));
-}
-```
-
-This won't work, however, and will give us the error:
-
-```text
-13:9: 13:22 error: the trait bound `alloc::rc::Rc<collections::vec::Vec<i32>> : core::marker::Send`
-            is not satisfied
-...
-13:9: 13:22 note: `alloc::rc::Rc<collections::vec::Vec<i32>>`
-            cannot be sent between threads safely
-```
-
-As the error message mentions, `Rc` cannot be sent between threads safely. This
-is because the internal reference count is not maintained in a thread safe
-matter and can have a data race.
-
-To solve this, we'll use `Arc<T>`, Rust's standard atomic reference count type.
-
-The Atomic part means `Arc<T>` can safely be accessed from multiple threads.
-To do this the compiler guarantees that mutations of the internal count use
-indivisible operations which can't have data races.
-
-In essence, `Arc<T>` is a type that lets us share ownership of data _across
-threads_.
-
-
-```rust,ignore
-use std::thread;
-use std::sync::Arc;
-use std::time::Duration;
-
-fn main() {
-    let mut data = Arc::new(vec![1, 2, 3]);
-
-    for i in 0..3 {
-        let data = data.clone();
-        thread::spawn(move || {
-            data[0] += i;
-        });
-    }
-
-    thread::sleep(Duration::from_millis(50));
-}
-```
-
-Similarly to last time, we use `clone()` to create a new owned handle.
-This handle is then moved into the new thread.
-
-And... still gives us an error.
-
-```text
-<anon>:11:24 error: cannot borrow immutable borrowed content as mutable
-<anon>:11                    data[0] += i;
-                             ^~~~
-```
-
-`Arc<T>` by default has immutable contents. It allows the _sharing_ of data
-between threads, but shared mutable data is unsafe—and when threads are
-involved—can cause data races!
-
-
-Usually when we wish to make something in an immutable position mutable, we use
-`Cell<T>` or `RefCell<T>` which allow safe mutation via runtime checks or
-otherwise (see also: [Choosing Your Guarantees](choosing-your-guarantees.html)).
-However, similar to `Rc`, these are not thread safe. If we try using these, we
-will get an error about these types not being `Sync`, and the code will fail to
-compile.
-
-It looks like we need some type that allows us to safely mutate a shared value
-across threads, for example a type that can ensure only one thread at a time is
-able to mutate the value inside it at any one time.
-
-For that, we can use the `Mutex<T>` type!
-
-Here's the working version:
-
-```rust
-use std::sync::{Arc, Mutex};
-use std::thread;
-use std::time::Duration;
-
-fn main() {
-    let data = Arc::new(Mutex::new(vec![1, 2, 3]));
-
-    for i in 0..3 {
-        let data = data.clone();
-        thread::spawn(move || {
-            let mut data = data.lock().unwrap();
-            data[0] += i;
-        });
-    }
-
-    thread::sleep(Duration::from_millis(50));
-}
-```
-
-Note that the value of `i` is bound (copied) to the closure and not shared
-among the threads.
-
-We're "locking" the mutex here. A mutex (short for "mutual exclusion"), as
-mentioned, only allows one thread at a time to access a value. When we wish to
-access the value, we use `lock()` on it. This will "lock" the mutex, and no
-other thread will be able to lock it (and hence, do anything with the value)
-until we're done with it. If a thread attempts to lock a mutex which is already
-locked, it will wait until the other thread releases the lock.
-
-The lock "release" here is implicit; when the result of the lock (in this case,
-`data`) goes out of scope, the lock is automatically released.
-
-Note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of
-[`Mutex`](../std/sync/struct.Mutex.html) has this signature:
-
-```rust,ignore
-fn lock(&self) -> LockResult<MutexGuard<T>>
-```
-
-and because `Send` is not implemented for `MutexGuard<T>`, the guard cannot
-cross thread boundaries, ensuring thread-locality of lock acquire and release.
-
-Let's examine the body of the thread more closely:
-
-```rust
-# use std::sync::{Arc, Mutex};
-# use std::thread;
-# use std::time::Duration;
-# fn main() {
-#     let data = Arc::new(Mutex::new(vec![1, 2, 3]));
-#     for i in 0..3 {
-#         let data = data.clone();
-thread::spawn(move || {
-    let mut data = data.lock().unwrap();
-    data[0] += i;
-});
-#     }
-#     thread::sleep(Duration::from_millis(50));
-# }
-```
-
-First, we call `lock()`, which acquires the mutex's lock. Because this may fail,
-it returns a `Result<T, E>`, and because this is just an example, we `unwrap()`
-it to get a reference to the data. Real code would have more robust error handling
-here. We're then free to mutate it, since we have the lock.
-
-Lastly, while the threads are running, we wait on a short timer. But
-this is not ideal: we may have picked a reasonable amount of time to
-wait but it's more likely we'll either be waiting longer than
-necessary or not long enough, depending on just how much time the
-threads actually take to finish computing when the program runs.
-
-A more precise alternative to the timer would be to use one of the
-mechanisms provided by the Rust standard library for synchronizing
-threads with each other. Let's talk about one of them: channels.
-
-## Channels
-
-Here's a version of our code that uses channels for synchronization, rather
-than waiting for a specific time:
-
-```rust
-use std::sync::{Arc, Mutex};
-use std::thread;
-use std::sync::mpsc;
-
-fn main() {
-    let data = Arc::new(Mutex::new(0));
-
-    // `tx` is the "transmitter" or "sender".
-    // `rx` is the "receiver".
-    let (tx, rx) = mpsc::channel();
-
-    for _ in 0..10 {
-        let (data, tx) = (data.clone(), tx.clone());
-
-        thread::spawn(move || {
-            let mut data = data.lock().unwrap();
-            *data += 1;
-
-            tx.send(()).unwrap();
-        });
-    }
-
-    for _ in 0..10 {
-        rx.recv().unwrap();
-    }
-}
-```
-
-We use the `mpsc::channel()` method to construct a new channel. We `send`
-a simple `()` down the channel, and then wait for ten of them to come back.
-
-While this channel is sending a generic signal, we can send any data that
-is `Send` over the channel!
-
-```rust
-use std::thread;
-use std::sync::mpsc;
-
-fn main() {
-    let (tx, rx) = mpsc::channel();
-
-    for i in 0..10 {
-        let tx = tx.clone();
-
-        thread::spawn(move || {
-            let answer = i * i;
-
-            tx.send(answer).unwrap();
-        });
-    }
-
-    for _ in 0..10 {
-        println!("{}", rx.recv().unwrap());
-    }
-}
-```
-
-Here we create 10 threads, asking each to calculate the square of a number (`i`
-at the time of `spawn()`), and then `send()` back the answer over the channel.
-
-
-## Panics
-
-A `panic!` will crash the currently executing thread. You can use Rust's
-threads as a simple isolation mechanism:
-
-```rust
-use std::thread;
-
-let handle = thread::spawn(move || {
-    panic!("oops!");
-});
-
-let result = handle.join();
-
-assert!(result.is_err());
-```
-
-`Thread.join()` gives us a `Result` back, which allows us to check if the thread
-has panicked or not.
diff --git a/src/doc/book/src/conditional-compilation.md b/src/doc/book/src/conditional-compilation.md
deleted file mode 100644 (file)
index 0562e9f..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-# Conditional Compilation
-
-Rust has a special attribute, `#[cfg]`, which allows you to compile code
-based on a flag passed to the compiler. It has two forms:
-
-```rust
-#[cfg(foo)]
-# fn foo() {}
-
-#[cfg(bar = "baz")]
-# fn bar() {}
-```
-
-They also have some helpers:
-
-```rust
-#[cfg(any(unix, windows))]
-# fn foo() {}
-
-#[cfg(all(unix, target_pointer_width = "32"))]
-# fn bar() {}
-
-#[cfg(not(foo))]
-# fn not_foo() {}
-```
-
-These can nest arbitrarily:
-
-```rust
-#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))]
-# fn foo() {}
-```
-
-As for how to enable or disable these switches, if you’re using Cargo,
-they get set in the [`[features]` section][features] of your `Cargo.toml`:
-
-[features]: http://doc.crates.io/manifest.html#the-features-section
-
-```toml
-[features]
-# no features by default
-default = []
-
-# Add feature "foo" here, then you can use it. 
-# Our "foo" feature depends on nothing else.
-foo = []
-```
-
-When you do this, Cargo passes along a flag to `rustc`:
-
-```text
---cfg feature="${feature_name}"
-```
-
-The sum of these `cfg` flags will determine which ones get activated, and
-therefore, which code gets compiled. Let’s take this code:
-
-```rust
-#[cfg(feature = "foo")]
-mod foo {
-}
-```
-
-If we compile it with `cargo build --features "foo"`, it will send the `--cfg
-feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it.
-If we compile it with a regular `cargo build`, no extra flags get passed on,
-and so, no `foo` module will exist.
-
-# cfg_attr
-
-You can also set another attribute based on a `cfg` variable with `cfg_attr`:
-
-```rust
-#[cfg_attr(a, b)]
-# fn foo() {}
-```
-
-Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise.
-
-# cfg!
-
-The `cfg!` macro lets you use these kinds of flags elsewhere in your code, too:
-
-```rust
-if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
-    println!("Think Different!");
-}
-```
-
-These will be replaced by a `true` or `false` at compile-time, depending on the
-configuration settings.
diff --git a/src/doc/book/src/const-and-static.md b/src/doc/book/src/const-and-static.md
deleted file mode 100644 (file)
index 66a4856..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-# const and static
-
-Rust has a way of defining constants with the `const` keyword:
-
-```rust
-const N: i32 = 5;
-```
-
-Unlike [`let`][let] bindings, you must annotate the type of a `const`.
-
-[let]: variable-bindings.html
-
-Constants live for the entire lifetime of a program. More specifically,
-constants in Rust have no fixed address in memory. This is because they’re
-effectively inlined to each place that they’re used. References to the same
-constant are not necessarily guaranteed to refer to the same memory address for
-this reason.
-
-# `static`
-
-Rust provides a ‘global variable’ sort of facility in static items. They’re
-similar to constants, but static items aren’t inlined upon use. This means that
-there is only one instance for each value, and it’s at a fixed location in
-memory.
-
-Here’s an example:
-
-```rust
-static N: i32 = 5;
-```
-
-Unlike [`let`][let] bindings, you must annotate the type of a `static`.
-
-Statics live for the entire lifetime of a program, and therefore any
-reference stored in a static has a [`'static` lifetime][lifetimes]:
-
-```rust
-static NAME: &'static str = "Steve";
-```
-
-[lifetimes]: lifetimes.html
-
-## Mutability
-
-You can introduce mutability with the `mut` keyword:
-
-```rust
-static mut N: i32 = 5;
-```
-
-Because this is mutable, one thread could be updating `N` while another is
-reading it, causing memory unsafety. As such both accessing and mutating a
-`static mut` is [`unsafe`][unsafe], and so must be done in an `unsafe` block:
-
-```rust
-# static mut N: i32 = 5;
-
-unsafe {
-    N += 1;
-
-    println!("N: {}", N);
-}
-```
-
-[unsafe]: unsafe.html
-
-Furthermore, any type stored in a `static` must be `Sync`, and must not have
-a [`Drop`][drop] implementation.
-
-[drop]: drop.html
-
-# Initializing
-
-Both `const` and `static` have requirements for giving them a value. They must
-be given a value that’s a constant expression. In other words, you cannot use
-the result of a function call or anything similarly complex or at runtime.
-
-# Which construct should I use?
-
-Almost always, if you can choose between the two, choose `const`. It’s pretty
-rare that you actually want a memory location associated with your constant,
-and using a `const` allows for optimizations like constant propagation not only
-in your crate but downstream crates.
diff --git a/src/doc/book/src/crates-and-modules.md b/src/doc/book/src/crates-and-modules.md
deleted file mode 100644 (file)
index 84f5fac..0000000
+++ /dev/null
@@ -1,593 +0,0 @@
-# Crates and Modules
-
-When a project starts getting large, it’s considered good software
-engineering practice to split it up into a bunch of smaller pieces, and then
-fit them together. It is also important to have a well-defined interface, so
-that some of your functionality is private, and some is public. To facilitate
-these kinds of things, Rust has a module system.
-
-# Basic terminology: Crates and Modules
-
-Rust has two distinct terms that relate to the module system: ‘crate’ and
-‘module’. A crate is synonymous with a ‘library’ or ‘package’ in other
-languages. Hence “Cargo” as the name of Rust’s package management tool: you
-ship your crates to others with Cargo. Crates can produce an executable or a
-library, depending on the project.
-
-Each crate has an implicit *root module* that contains the code for that crate.
-You can then define a tree of sub-modules under that root module. Modules allow
-you to partition your code within the crate itself.
-
-As an example, let’s make a *phrases* crate, which will give us various phrases
-in different languages. To keep things simple, we’ll stick to ‘greetings’ and
-‘farewells’ as two kinds of phrases, and use English and Japanese (日本語) as
-two languages for those phrases to be in. We’ll use this module layout:
-
-```text
-                                    +-----------+
-                                +---| greetings |
-                  +---------+   |   +-----------+
-              +---| english |---+
-              |   +---------+   |   +-----------+
-              |                 +---| farewells |
-+---------+   |                     +-----------+
-| phrases |---+
-+---------+   |                     +-----------+
-              |                 +---| greetings |
-              |   +----------+  |   +-----------+
-              +---| japanese |--+
-                  +----------+  |   +-----------+
-                                +---| farewells |
-                                    +-----------+
-```
-
-In this example, `phrases` is the name of our crate. All of the rest are
-modules.  You can see that they form a tree, branching out from the crate
-*root*, which is the root of the tree: `phrases` itself.
-
-Now that we have a plan, let’s define these modules in code. To start,
-generate a new crate with Cargo:
-
-```bash
-$ cargo new phrases
-$ cd phrases
-```
-
-If you remember, this generates a simple project for us:
-
-```bash
-$ tree .
-.
-├── Cargo.toml
-└── src
-    └── lib.rs
-
-1 directory, 2 files
-```
-
-`src/lib.rs` is our crate root, corresponding to the `phrases` in our diagram
-above.
-
-# Defining Modules
-
-To define each of our modules, we use the `mod` keyword. Let’s make our
-`src/lib.rs` look like this:
-
-```rust
-mod english {
-    mod greetings {
-    }
-
-    mod farewells {
-    }
-}
-
-mod japanese {
-    mod greetings {
-    }
-
-    mod farewells {
-    }
-}
-```
-
-After the `mod` keyword, you give the name of the module. Module names follow
-the conventions for other Rust identifiers: `lower_snake_case`. The contents of
-each module are within curly braces (`{}`).
-
-Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules
-with double-colon (`::`) notation: our four nested modules are
-`english::greetings`, `english::farewells`, `japanese::greetings`, and
-`japanese::farewells`. Because these sub-modules are namespaced under their
-parent module, the names don’t conflict: `english::greetings` and
-`japanese::greetings` are distinct, even though their names are both
-`greetings`.
-
-Because this crate does not have a `main()` function, and is called `lib.rs`,
-Cargo will build this crate as a library:
-
-```bash
-$ cargo build
-   Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
-$ ls target/debug
-build  deps  examples  libphrases-a7448e02a0468eaa.rlib  native
-```
-
-`libphrases-<hash>.rlib` is the compiled crate. Before we see how to use this
-crate from another crate, let’s break it up into multiple files.
-
-# Multiple File Crates
-
-If each crate were just one file, these files would get very large. It’s often
-easier to split up crates into multiple files, and Rust supports this in two
-ways.
-
-Instead of declaring a module like this:
-
-```rust,ignore
-mod english {
-    // Contents of our module go here.
-}
-```
-
-We can instead declare our module like this:
-
-```rust,ignore
-mod english;
-```
-
-If we do that, Rust will expect to find either a `english.rs` file, or a
-`english/mod.rs` file with the contents of our module.
-
-Note that in these files, you don’t need to re-declare the module: that’s
-already been done with the initial `mod` declaration.
-
-Using these two techniques, we can break up our crate into two directories and
-seven files:
-
-```bash
-$ tree .
-.
-├── Cargo.lock
-├── Cargo.toml
-├── src
-│   ├── english
-│   │   ├── farewells.rs
-│   │   ├── greetings.rs
-│   │   └── mod.rs
-│   ├── japanese
-│   │   ├── farewells.rs
-│   │   ├── greetings.rs
-│   │   └── mod.rs
-│   └── lib.rs
-└── target
-    └── debug
-        ├── build
-        ├── deps
-        ├── examples
-        ├── libphrases-a7448e02a0468eaa.rlib
-        └── native
-```
-
-`src/lib.rs` is our crate root, and looks like this:
-
-```rust,ignore
-mod english;
-mod japanese;
-```
-
-These two declarations tell Rust to look for either `src/english.rs` and
-`src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending
-on our preference. In this case, because our modules have sub-modules, we’ve
-chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
-like this:
-
-```rust,ignore
-mod greetings;
-mod farewells;
-```
-
-Again, these declarations tell Rust to look for either
-`src/english/greetings.rs`, `src/english/farewells.rs`,
-`src/japanese/greetings.rs` and `src/japanese/farewells.rs` or
-`src/english/greetings/mod.rs`, `src/english/farewells/mod.rs`,
-`src/japanese/greetings/mod.rs` and
-`src/japanese/farewells/mod.rs`. Because these sub-modules don’t have
-their own sub-modules, we’ve chosen to make them
-`src/english/greetings.rs`, `src/english/farewells.rs`,
-`src/japanese/greetings.rs` and `src/japanese/farewells.rs`. Whew!
-
-The contents of `src/english/greetings.rs`,
-`src/english/farewells.rs`, `src/japanese/greetings.rs` and
-`src/japanese/farewells.rs` are all empty at the moment. Let’s add
-some functions.
-
-Put this in `src/english/greetings.rs`:
-
-```rust
-fn hello() -> String {
-    "Hello!".to_string()
-}
-```
-
-Put this in `src/english/farewells.rs`:
-
-```rust
-fn goodbye() -> String {
-    "Goodbye.".to_string()
-}
-```
-
-Put this in `src/japanese/greetings.rs`:
-
-```rust
-fn hello() -> String {
-    "こんにちは".to_string()
-}
-```
-
-Of course, you can copy and paste this from this web page, or type
-something else. It’s not important that you actually put ‘konnichiwa’ to learn
-about the module system.
-
-Put this in `src/japanese/farewells.rs`:
-
-```rust
-fn goodbye() -> String {
-    "さようなら".to_string()
-}
-```
-
-(This is ‘Sayōnara’, if you’re curious.)
-
-Now that we have some functionality in our crate, let’s try to use it from
-another crate.
-
-# Importing External Crates
-
-We have a library crate. Let’s make an executable crate that imports and uses
-our library.
-
-Make a `src/main.rs` and put this in it (it won’t quite compile yet):
-
-```rust,ignore
-extern crate phrases;
-
-fn main() {
-    println!("Hello in English: {}", phrases::english::greetings::hello());
-    println!("Goodbye in English: {}", phrases::english::farewells::goodbye());
-
-    println!("Hello in Japanese: {}", phrases::japanese::greetings::hello());
-    println!("Goodbye in Japanese: {}", phrases::japanese::farewells::goodbye());
-}
-```
-
-The `extern crate` declaration tells Rust that we need to compile and link to
-the `phrases` crate. We can then use `phrases`’ modules in this one. As we
-mentioned earlier, you can use double colons to refer to sub-modules and the
-functions inside of them.
-
-(Note: when importing a crate that has dashes in its name "like-this", which is
-not a valid Rust identifier, it will be converted by changing the dashes to
-underscores, so you would write `extern crate like_this;`.)
-
-Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate,
-rather than a library crate. Our package now has two crates: `src/lib.rs` and
-`src/main.rs`. This pattern is quite common for executable crates: most
-functionality is in a library crate, and the executable crate uses that
-library. This way, other programs can also use the library crate, and it’s also
-a nice separation of concerns.
-
-This doesn’t quite work yet, though. We get four errors that look similar to
-this:
-
-```bash
-$ cargo build
-   Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
-src/main.rs:4:38: 4:72 error: function `hello` is private
-src/main.rs:4     println!("Hello in English: {}", phrases::english::greetings::hello());
-                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-note: in expansion of format_args!
-<std macros>:2:25: 2:58 note: expansion site
-<std macros>:1:1: 2:62 note: in expansion of print!
-<std macros>:3:1: 3:54 note: expansion site
-<std macros>:1:1: 3:58 note: in expansion of println!
-phrases/src/main.rs:4:5: 4:76 note: expansion site
-```
-
-By default, everything is private in Rust. Let’s talk about this in some more
-depth.
-
-# Exporting a Public Interface
-
-Rust allows you to precisely control which aspects of your interface are
-public, and so private is the default. To make things public, you use the `pub`
-keyword. Let’s focus on the `english` module first, so let’s reduce our `src/main.rs`
-to only this:
-
-```rust,ignore
-extern crate phrases;
-
-fn main() {
-    println!("Hello in English: {}", phrases::english::greetings::hello());
-    println!("Goodbye in English: {}", phrases::english::farewells::goodbye());
-}
-```
-
-In our `src/lib.rs`, let’s add `pub` to the `english` module declaration:
-
-```rust,ignore
-pub mod english;
-mod japanese;
-```
-
-And in our `src/english/mod.rs`, let’s make both `pub`:
-
-```rust,ignore
-pub mod greetings;
-pub mod farewells;
-```
-
-In our `src/english/greetings.rs`, let’s add `pub` to our `fn` declaration:
-
-```rust,ignore
-pub fn hello() -> String {
-    "Hello!".to_string()
-}
-```
-
-And also in `src/english/farewells.rs`:
-
-```rust,ignore
-pub fn goodbye() -> String {
-    "Goodbye.".to_string()
-}
-```
-
-Now, our crate compiles, albeit with warnings about not using the `japanese`
-functions:
-
-```bash
-$ cargo run
-   Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
-src/japanese/greetings.rs:1:1: 3:2 warning: function is never used: `hello`, #[warn(dead_code)] on by default
-src/japanese/greetings.rs:1 fn hello() -> String {
-src/japanese/greetings.rs:2     "こんにちは".to_string()
-src/japanese/greetings.rs:3 }
-src/japanese/farewells.rs:1:1: 3:2 warning: function is never used: `goodbye`, #[warn(dead_code)] on by default
-src/japanese/farewells.rs:1 fn goodbye() -> String {
-src/japanese/farewells.rs:2     "さようなら".to_string()
-src/japanese/farewells.rs:3 }
-     Running `target/debug/phrases`
-Hello in English: Hello!
-Goodbye in English: Goodbye.
-```
-
-`pub` also applies to `struct`s and their member fields. In keeping with Rust’s
-tendency toward safety, simply making a `struct` public won't automatically
-make its members public: you must mark the fields individually with `pub`.
-
-Now that our functions are public, we can use them. Great! However, typing out
-`phrases::english::greetings::hello()` is very long and repetitive. Rust has
-another keyword for importing names into the current scope, so that you can
-refer to them with shorter names. Let’s talk about `use`.
-
-# Importing Modules with `use`
-
-Rust has a `use` keyword, which allows us to import names into our local scope.
-Let’s change our `src/main.rs` to look like this:
-
-```rust,ignore
-extern crate phrases;
-
-use phrases::english::greetings;
-use phrases::english::farewells;
-
-fn main() {
-    println!("Hello in English: {}", greetings::hello());
-    println!("Goodbye in English: {}", farewells::goodbye());
-}
-```
-
-The two `use` lines import each module into the local scope, so we can refer to
-the functions by a much shorter name. By convention, when importing functions, it’s
-considered best practice to import the module, rather than the function directly. In
-other words, you _can_ do this:
-
-```rust,ignore
-extern crate phrases;
-
-use phrases::english::greetings::hello;
-use phrases::english::farewells::goodbye;
-
-fn main() {
-    println!("Hello in English: {}", hello());
-    println!("Goodbye in English: {}", goodbye());
-}
-```
-
-But it is not idiomatic. This is significantly more likely to introduce a
-naming conflict. In our short program, it’s not a big deal, but as it grows, it
-becomes a problem. If we have conflicting names, Rust will give a compilation
-error. For example, if we made the `japanese` functions public, and tried to do
-this:
-
-```rust,ignore
-extern crate phrases;
-
-use phrases::english::greetings::hello;
-use phrases::japanese::greetings::hello;
-
-fn main() {
-    println!("Hello in English: {}", hello());
-    println!("Hello in Japanese: {}", hello());
-}
-```
-
-Rust will give us a compile-time error:
-
-```text
-   Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
-src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module [E0252]
-src/main.rs:4 use phrases::japanese::greetings::hello;
-                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-error: aborting due to previous error
-Could not compile `phrases`.
-```
-
-If we’re importing multiple names from the same module, we don’t have to type it out
-twice. Instead of this:
-
-```rust,ignore
-use phrases::english::greetings;
-use phrases::english::farewells;
-```
-
-We can use this shortcut:
-
-```rust,ignore
-use phrases::english::{greetings, farewells};
-```
-
-## Re-exporting with `pub use`
-
-You don’t only use `use` to shorten identifiers. You can also use it inside of your crate
-to re-export a function inside another module. This allows you to present an external
-interface that may not directly map to your internal code organization.
-
-Let’s look at an example. Modify your `src/main.rs` to read like this:
-
-```rust,ignore
-extern crate phrases;
-
-use phrases::english::{greetings,farewells};
-use phrases::japanese;
-
-fn main() {
-    println!("Hello in English: {}", greetings::hello());
-    println!("Goodbye in English: {}", farewells::goodbye());
-
-    println!("Hello in Japanese: {}", japanese::hello());
-    println!("Goodbye in Japanese: {}", japanese::goodbye());
-}
-```
-
-Then, modify your `src/lib.rs` to make the `japanese` mod public:
-
-```rust,ignore
-pub mod english;
-pub mod japanese;
-```
-
-Next, make the two functions public, first in `src/japanese/greetings.rs`:
-
-```rust,ignore
-pub fn hello() -> String {
-    "こんにちは".to_string()
-}
-```
-
-And then in `src/japanese/farewells.rs`:
-
-```rust,ignore
-pub fn goodbye() -> String {
-    "さようなら".to_string()
-}
-```
-
-Finally, modify your `src/japanese/mod.rs` to read like this:
-
-```rust,ignore
-pub use self::greetings::hello;
-pub use self::farewells::goodbye;
-
-mod greetings;
-mod farewells;
-```
-
-The `pub use` declaration brings the function into scope at this part of our
-module hierarchy. Because we’ve `pub use`d this inside of our `japanese`
-module, we now have a `phrases::japanese::hello()` function and a
-`phrases::japanese::goodbye()` function, even though the code for them lives in
-`phrases::japanese::greetings::hello()` and
-`phrases::japanese::farewells::goodbye()`. Our internal organization doesn’t
-define our external interface.
-
-Here we have a `pub use` for each function we want to bring into the
-`japanese` scope. We could alternatively use the wildcard syntax to include
-everything from `greetings` into the current scope: `pub use self::greetings::*`.
-
-What about the `self`? Well, by default, `use` declarations are absolute paths,
-starting from your crate root. `self` makes that path relative to your current
-place in the hierarchy instead. There’s one more special form of `use`: you can
-`use super::` to reach one level up the tree from your current location. Some
-people like to think of `self` as `.` and `super` as `..`, from many shells’
-display for the current directory and the parent directory.
-
-Outside of `use`, paths are relative: `foo::bar()` refers to a function inside
-of `foo` relative to where we are. If that’s prefixed with `::`, as in
-`::foo::bar()`, it refers to a different `foo`, an absolute path from your
-crate root.
-
-This will build and run:
-
-```bash
-$ cargo run
-   Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
-     Running `target/debug/phrases`
-Hello in English: Hello!
-Goodbye in English: Goodbye.
-Hello in Japanese: こんにちは
-Goodbye in Japanese: さようなら
-```
-
-## Complex imports
-
-Rust offers several advanced options that can add compactness and
-convenience to your `extern crate` and `use` statements. Here is an example:
-
-```rust,ignore
-extern crate phrases as sayings;
-
-use sayings::japanese::greetings as ja_greetings;
-use sayings::japanese::farewells::*;
-use sayings::english::{self, greetings as en_greetings, farewells as en_farewells};
-
-fn main() {
-    println!("Hello in English; {}", en_greetings::hello());
-    println!("And in Japanese: {}", ja_greetings::hello());
-    println!("Goodbye in English: {}", english::farewells::goodbye());
-    println!("Again: {}", en_farewells::goodbye());
-    println!("And in Japanese: {}", goodbye());
-}
-```
-
-What's going on here?
-
-First, both `extern crate` and `use` allow renaming the thing that is being
-imported. So the crate is still called "phrases", but here we will refer
-to it as "sayings". Similarly, the first `use` statement pulls in the
-`japanese::greetings` module from the crate, but makes it available as
-`ja_greetings` as opposed to simply `greetings`. This can help to avoid
-ambiguity when importing similarly-named items from different places.
-
-The second `use` statement uses a star glob to bring in all public symbols from
-the `sayings::japanese::farewells` module. As you can see we can later refer to
-the Japanese `goodbye` function with no module qualifiers. This kind of glob
-should be used sparingly. It’s worth noting that it only imports the public
-symbols, even if the code doing the globbing is in the same module.
-
-The third `use` statement bears more explanation. It's using "brace expansion"
-globbing to compress three `use` statements into one (this sort of syntax
-may be familiar if you've written Linux shell scripts before). The
-uncompressed form of this statement would be:
-
-```rust,ignore
-use sayings::english;
-use sayings::english::greetings as en_greetings;
-use sayings::english::farewells as en_farewells;
-```
-
-As you can see, the curly brackets compress `use` statements for several items
-under the same path, and in this context `self` refers back to that path.
-Note: The curly brackets cannot be nested or mixed with star globbing.
diff --git a/src/doc/book/src/deref-coercions.md b/src/doc/book/src/deref-coercions.md
deleted file mode 100644 (file)
index 8552a7c..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-# `Deref` coercions
-
-The standard library provides a special trait, [`Deref`][deref]. It’s normally
-used to overload `*`, the dereference operator:
-
-```rust
-use std::ops::Deref;
-
-struct DerefExample<T> {
-    value: T,
-}
-
-impl<T> Deref for DerefExample<T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        &self.value
-    }
-}
-
-fn main() {
-    let x = DerefExample { value: 'a' };
-    assert_eq!('a', *x);
-}
-```
-
-[deref]: ../std/ops/trait.Deref.html
-
-This is useful for writing custom pointer types. However, there’s a language
-feature related to `Deref`: ‘deref coercions’. Here’s the rule: If you have a
-type `U`, and it implements `Deref<Target=T>`, values of `&U` will
-automatically coerce to a `&T`. Here’s an example:
-
-```rust
-fn foo(s: &str) {
-    // Borrow a string for a second.
-}
-
-// String implements Deref<Target=str>.
-let owned = "Hello".to_string();
-
-// Therefore, this works:
-foo(&owned);
-```
-
-Using an ampersand in front of a value takes a reference to it. So `owned` is a
-`String`, `&owned` is an `&String`, and since `impl Deref<Target=str> for
-String`, `&String` will deref to `&str`, which `foo()` takes.
-
-That’s it. This rule is one of the only places in which Rust does an automatic
-conversion for you, but it adds a lot of flexibility. For example, the `Rc<T>`
-type implements `Deref<Target=T>`, so this works:
-
-```rust
-use std::rc::Rc;
-
-fn foo(s: &str) {
-    // Borrow a string for a second.
-}
-
-// String implements Deref<Target=str>.
-let owned = "Hello".to_string();
-let counted = Rc::new(owned);
-
-// Therefore, this works:
-foo(&counted);
-```
-
-All we’ve done is wrap our `String` in an `Rc<T>`. But we can now pass the
-`Rc<String>` around anywhere we’d have a `String`. The signature of `foo`
-didn’t change, but works just as well with either type. This example has two
-conversions: `&Rc<String>` to `&String` and then `&String` to `&str`. Rust will do
-this as many times as possible until the types match.
-
-Another very common implementation provided by the standard library is:
-
-```rust
-fn foo(s: &[i32]) {
-    // Borrow a slice for a second.
-}
-
-// Vec<T> implements Deref<Target=[T]>.
-let owned = vec![1, 2, 3];
-
-foo(&owned);
-```
-
-Vectors can `Deref` to a slice.
-
-## Deref and method calls
-
-`Deref` will also kick in when calling a method. Consider the following
-example.
-
-```rust
-struct Foo;
-
-impl Foo {
-    fn foo(&self) { println!("Foo"); }
-}
-
-let f = &&Foo;
-
-f.foo();
-```
-
-Even though `f` is a `&&Foo` and `foo` takes `&self`, this works. That’s
-because these things are the same:
-
-```rust,ignore
-f.foo();
-(&f).foo();
-(&&f).foo();
-(&&&&&&&&f).foo();
-```
-
-A value of type `&&&&&&&&&&&&&&&&Foo` can still have methods defined on `Foo`
-called, because the compiler will insert as many * operations as necessary to
-get it right. And since it’s inserting `*`s, that uses `Deref`.
diff --git a/src/doc/book/src/documentation.md b/src/doc/book/src/documentation.md
deleted file mode 100644 (file)
index 176a7e5..0000000
+++ /dev/null
@@ -1,655 +0,0 @@
-# Documentation
-
-Documentation is an important part of any software project, and it's
-first-class in Rust. Let's talk about the tooling Rust gives you to
-document your project.
-
-## About `rustdoc`
-
-The Rust distribution includes a tool, `rustdoc`, that generates documentation.
-`rustdoc` is also used by Cargo through `cargo doc`.
-
-Documentation can be generated in two ways: from source code, and from
-standalone Markdown files.
-
-## Documenting source code
-
-The primary way of documenting a Rust project is through annotating the source
-code. You can use documentation comments for this purpose:
-
-```rust,ignore
-/// Constructs a new `Rc<T>`.
-///
-/// # Examples
-///
-/// ```
-/// use std::rc::Rc;
-///
-/// let five = Rc::new(5);
-/// ```
-pub fn new(value: T) -> Rc<T> {
-    // Implementation goes here.
-}
-```
-
-This code generates documentation that looks [like this][rc-new]. I've left the
-implementation out, with a regular comment in its place.
-
-The first thing to notice about this annotation is that it uses
-`///` instead of `//`. The triple slash
-indicates a documentation comment.
-
-Documentation comments are written in Markdown.
-
-Rust keeps track of these comments, and uses them when generating
-documentation. This is important when documenting things like enums:
-
-```rust
-/// The `Option` type. See [the module level documentation](index.html) for more.
-enum Option<T> {
-    /// No value
-    None,
-    /// Some value `T`
-    Some(T),
-}
-```
-
-The above works, but this does not:
-
-```rust,ignore
-/// The `Option` type. See [the module level documentation](index.html) for more.
-enum Option<T> {
-    None, /// No value
-    Some(T), /// Some value `T`
-}
-```
-
-You'll get an error:
-
-```text
-hello.rs:4:1: 4:2 error: expected ident, found `}`
-hello.rs:4 }
-           ^
-```
-
-This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is
-correct; documentation comments apply to the thing after them, and there's
-nothing after that last comment.
-
-[rc-new]: ../std/rc/struct.Rc.html#method.new
-
-### Writing documentation comments
-
-Anyway, let's cover each part of this comment in detail:
-
-```rust
-/// Constructs a new `Rc<T>`.
-# fn foo() {}
-```
-
-The first line of a documentation comment should be a short summary of its
-functionality. One sentence. Just the basics. High level.
-
-```rust
-///
-/// Other details about constructing `Rc<T>`s, maybe describing complicated
-/// semantics, maybe additional options, all kinds of stuff.
-///
-# fn foo() {}
-```
-
-Our original example had just a summary line, but if we had more things to say,
-we could have added more explanation in a new paragraph.
-
-#### Special sections
-
-Next, are special sections. These are indicated with a header, `#`. There
-are four kinds of headers that are commonly used. They aren't special syntax,
-just convention, for now.
-
-```rust
-/// # Panics
-# fn foo() {}
-```
-
-Unrecoverable misuses of a function (i.e. programming errors) in Rust are
-usually indicated by panics, which kill the whole current thread at the very
-least. If your function has a non-trivial contract like this, that is
-detected/enforced by panics, documenting it is very important.
-
-```rust
-/// # Errors
-# fn foo() {}
-```
-
-If your function or method returns a `Result<T, E>`, then describing the
-conditions under which it returns `Err(E)` is a nice thing to do. This is
-slightly less important than `Panics`, because failure is encoded into the type
-system, but it's still a good thing to do.
-
-```rust
-/// # Safety
-# fn foo() {}
-```
-
-If your function is `unsafe`, you should explain which invariants the caller is
-responsible for upholding.
-
-```rust
-/// # Examples
-///
-/// ```
-/// use std::rc::Rc;
-///
-/// let five = Rc::new(5);
-/// ```
-# fn foo() {}
-```
-
-Fourth, `Examples`. Include one or more examples of using your function or
-method, and your users will love you for it. These examples go inside of
-code block annotations, which we'll talk about in a moment, and can have
-more than one section:
-
-```rust
-/// # Examples
-///
-/// Simple `&str` patterns:
-///
-/// ```
-/// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
-/// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
-/// ```
-///
-/// More complex patterns with a lambda:
-///
-/// ```
-/// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
-/// assert_eq!(v, vec!["abc", "def", "ghi"]);
-/// ```
-# fn foo() {}
-```
-
-#### Code block annotations
-
-To write some Rust code in a comment, use the triple graves:
-
-```rust
-/// ```
-/// println!("Hello, world");
-/// ```
-# fn foo() {}
-```
-
-This will add code highlighting. If you are only showing plain text, put `text`
-instead of `rust` after the triple graves (see below).
-
-## Documentation as tests
-
-Let's discuss our sample example documentation:
-
-```rust
-/// ```
-/// println!("Hello, world");
-/// ```
-# fn foo() {}
-```
-
-You'll notice that you don't need a `fn main()` or anything here. `rustdoc` will
-automatically add a `main()` wrapper around your code, using heuristics to attempt
-to put it in the right place. For example:
-
-```rust
-/// ```
-/// use std::rc::Rc;
-///
-/// let five = Rc::new(5);
-/// ```
-# fn foo() {}
-```
-
-This will end up testing:
-
-```rust
-fn main() {
-    use std::rc::Rc;
-    let five = Rc::new(5);
-}
-```
-
-Here's the full algorithm rustdoc uses to preprocess examples:
-
-1. Any leading `#![foo]` attributes are left intact as crate attributes.
-2. Some common `allow` attributes are inserted, including
-   `unused_variables`, `unused_assignments`, `unused_mut`,
-   `unused_attributes`, and `dead_code`. Small examples often trigger
-   these lints.
-3. If the example does not contain `extern crate`, then `extern crate
-   <mycrate>;` is inserted (note the lack of `#[macro_use]`).
-4. Finally, if the example does not contain `fn main`, the remainder of the
-   text is wrapped in `fn main() { your_code }`.
-
-This generated `fn main` can be a problem! If you have `extern crate` or a `mod`
-statements in the example code that are referred to by `use` statements, they will
-fail to resolve unless you include at least `fn main() {}` to inhibit step 4.
-`#[macro_use] extern crate` also does not work except at the crate root, so when
-testing macros an explicit `main` is always required. It doesn't have to clutter
-up your docs, though -- keep reading!
-
-Sometimes this algorithm isn't enough, though. For example, all of these code samples
-with `///` we've been talking about? The raw text:
-
-```text
-/// Some documentation.
-# fn foo() {}
-```
-
-looks different than the output:
-
-```rust
-/// Some documentation.
-# fn foo() {}
-```
-
-Yes, that's right: you can add lines that start with `# `, and they will
-be hidden from the output, but will be used when compiling your code. You
-can use this to your advantage. In this case, documentation comments need
-to apply to some kind of function, so if I want to show you just a
-documentation comment, I need to add a little function definition below
-it. At the same time, it's only there to satisfy the compiler, so hiding
-it makes the example more clear. You can use this technique to explain
-longer examples in detail, while still preserving the testability of your
-documentation.
-
-For example, imagine that we wanted to document this code:
-
-```rust
-let x = 5;
-let y = 6;
-println!("{}", x + y);
-```
-
-We might want the documentation to end up looking like this:
-
-> First, we set `x` to five:
->
-> ```rust
-> let x = 5;
-> # let y = 6;
-> # println!("{}", x + y);
-> ```
->
-> Next, we set `y` to six:
->
-> ```rust
-> # let x = 5;
-> let y = 6;
-> # println!("{}", x + y);
-> ```
->
-> Finally, we print the sum of `x` and `y`:
->
-> ```rust
-> # let x = 5;
-> # let y = 6;
-> println!("{}", x + y);
-> ```
-
-To keep each code block testable, we want the whole program in each block, but
-we don't want the reader to see every line every time.  Here's what we put in
-our source code:
-
-```text
-    First, we set `x` to five:
-
-    ```rust
-    let x = 5;
-    # let y = 6;
-    # println!("{}", x + y);
-    ```
-
-    Next, we set `y` to six:
-
-    ```rust
-    # let x = 5;
-    let y = 6;
-    # println!("{}", x + y);
-    ```
-
-    Finally, we print the sum of `x` and `y`:
-
-    ```rust
-    # let x = 5;
-    # let y = 6;
-    println!("{}", x + y);
-    ```
-```
-
-By repeating all parts of the example, you can ensure that your example still
-compiles, while only showing the parts that are relevant to that part of your
-explanation.
-
-### Documenting macros
-
-Here’s an example of documenting a macro:
-
-```rust
-/// Panic with a given message unless an expression evaluates to true.
-///
-/// # Examples
-///
-/// ```
-/// # #[macro_use] extern crate foo;
-/// # fn main() {
-/// panic_unless!(1 + 1 == 2, “Math is broken.”);
-/// # }
-/// ```
-///
-/// ```rust,should_panic
-/// # #[macro_use] extern crate foo;
-/// # fn main() {
-/// panic_unless!(true == false, “I’m broken.”);
-/// # }
-/// ```
-#[macro_export]
-macro_rules! panic_unless {
-    ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } });
-}
-# fn main() {}
-```
-
-You’ll note three things: we need to add our own `extern crate` line, so that
-we can add the `#[macro_use]` attribute. Second, we’ll need to add our own
-`main()` as well (for reasons discussed above). Finally, a judicious use of
-`#` to comment out those two things, so they don’t show up in the output.
-
-Another case where the use of `#` is handy is when you want to ignore
-error handling. Lets say you want the following,
-
-```rust,ignore
-/// use std::io;
-/// let mut input = String::new();
-/// try!(io::stdin().read_line(&mut input));
-```
-
-The problem is that `try!` returns a `Result<T, E>` and test functions
-don't return anything so this will give a mismatched types error.
-
-```rust,ignore
-/// A doc test using try!
-///
-/// ```
-/// use std::io;
-/// # fn foo() -> io::Result<()> {
-/// let mut input = String::new();
-/// try!(io::stdin().read_line(&mut input));
-/// # Ok(())
-/// # }
-/// ```
-# fn foo() {}
-```
-
-You can get around this by wrapping the code in a function. This catches
-and swallows the `Result<T, E>` when running tests on the docs. This
-pattern appears regularly in the standard library.
-
-### Running documentation tests
-
-To run the tests, either:
-
-```bash
-$ rustdoc --test path/to/my/crate/root.rs
-# or
-$ cargo test
-```
-
-That's right, `cargo test` tests embedded documentation too. **However,
-`cargo test` will not test binary crates, only library ones.** This is
-due to the way `rustdoc` works: it links against the library to be tested,
-but with a binary, there’s nothing to link to.
-
-There are a few more annotations that are useful to help `rustdoc` do the right
-thing when testing your code:
-
-```rust
-/// ```rust,ignore
-/// fn foo() {
-/// ```
-# fn foo() {}
-```
-
-The `ignore` directive tells Rust to ignore your code. This is almost never
-what you want, as it's the most generic. Instead, consider annotating it
-with `text` if it's not code, or using `#`s to get a working example that
-only shows the part you care about.
-
-```rust
-/// ```rust,should_panic
-/// assert!(false);
-/// ```
-# fn foo() {}
-```
-
-`should_panic` tells `rustdoc` that the code should compile correctly, but
-not actually pass as a test.
-
-```rust
-/// ```rust,no_run
-/// loop {
-///     println!("Hello, world");
-/// }
-/// ```
-# fn foo() {}
-```
-
-The `no_run` attribute will compile your code, but not run it. This is
-important for examples such as "Here's how to retrieve a web page,"
-which you would want to ensure compiles, but might be run in a test
-environment that has no network access.
-
-### Documenting modules
-
-Rust has another kind of doc comment, `//!`. This comment doesn't document the next item, but the enclosing item. In other words:
-
-```rust
-mod foo {
-    //! This is documentation for the `foo` module.
-    //!
-    //! # Examples
-
-    // ...
-}
-```
-
-This is where you'll see `//!` used most often: for module documentation. If
-you have a module in `foo.rs`, you'll often open its code and see this:
-
-```rust
-//! A module for using `foo`s.
-//!
-//! The `foo` module contains a lot of useful functionality blah blah blah...
-```
-
-### Crate documentation
-
-Crates can be documented by placing an inner doc comment (`//!`) at the
-beginning of the crate root, aka `lib.rs`:
-
-```rust
-//! This is documentation for the `foo` crate.
-//!
-//! The foo crate is meant to be used for bar.
-```
-
-### Documentation comment style
-
-Check out [RFC 505][rfc505] for full conventions around the style and format of
-documentation.
-
-[rfc505]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md
-
-## Other documentation
-
-All of this behavior works in non-Rust source files too. Because comments
-are written in Markdown, they're often `.md` files.
-
-When you write documentation in Markdown files, you don't need to prefix
-the documentation with comments. For example:
-
-```rust
-/// # Examples
-///
-/// ```
-/// use std::rc::Rc;
-///
-/// let five = Rc::new(5);
-/// ```
-# fn foo() {}
-```
-
-is:
-
-~~~markdown
-# Examples
-
-```
-use std::rc::Rc;
-
-let five = Rc::new(5);
-```
-~~~
-
-when it's in a Markdown file. There is one wrinkle though: Markdown files need
-to have a title like this:
-
-```markdown
-% The title
-
-This is the example documentation.
-```
-
-This `%` line needs to be the very first line of the file.
-
-## `doc` attributes
-
-At a deeper level, documentation comments are syntactic sugar for documentation
-attributes:
-
-```rust
-/// this
-# fn foo() {}
-
-#[doc="this"]
-# fn bar() {}
-```
-
-are the same, as are these:
-
-```rust
-//! this
-
-#![doc="this"]
-```
-
-You won't often see this attribute used for writing documentation, but it
-can be useful when changing some options, or when writing a macro.
-
-### Re-exports
-
-`rustdoc` will show the documentation for a public re-export in both places:
-
-```rust,ignore
-extern crate foo;
-
-pub use foo::bar;
-```
-
-This will create documentation for `bar` both inside the documentation for the
-crate `foo`, as well as the documentation for your crate. It will use the same
-documentation in both places.
-
-This behavior can be suppressed with `no_inline`:
-
-```rust,ignore
-extern crate foo;
-
-#[doc(no_inline)]
-pub use foo::bar;
-```
-
-## Missing documentation
-
-Sometimes you want to make sure that every single public thing in your project
-is documented, especially when you are working on a library. Rust allows you to
-to generate warnings or errors, when an item is missing documentation.
-To generate warnings you use `warn`:
-
-```rust,ignore
-#![warn(missing_docs)]
-```
-
-And to generate errors you use `deny`:
-
-```rust,ignore
-#![deny(missing_docs)]
-```
-
-There are cases where you want to disable these warnings/errors to explicitly
-leave something undocumented. This is done by using `allow`:
-
-```rust
-#[allow(missing_docs)]
-struct Undocumented;
-```
-
-You might even want to hide items from the documentation completely:
-
-```rust
-#[doc(hidden)]
-struct Hidden;
-```
-
-### Controlling HTML
-
-You can control a few aspects of the HTML that `rustdoc` generates through the
-`#![doc]` version of the attribute:
-
-```rust,ignore
-#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
-       html_root_url = "https://doc.rust-lang.org/")]
-```
-
-This sets a few different options, with a logo, favicon, and a root URL.
-
-### Configuring documentation tests
-
-You can also configure the way that `rustdoc` tests your documentation examples
-through the `#![doc(test(..))]` attribute.
-
-```rust
-#![doc(test(attr(allow(unused_variables), deny(warnings))))]
-```
-
-This allows unused variables within the examples, but will fail the test for any
-other lint warning thrown.
-
-## Generation options
-
-`rustdoc` also contains a few other options on the command line, for further customization:
-
-- `--html-in-header FILE`: includes the contents of FILE at the end of the
-  `<head>...</head>` section.
-- `--html-before-content FILE`: includes the contents of FILE directly after
-  `<body>`, before the rendered content (including the search bar).
-- `--html-after-content FILE`: includes the contents of FILE after all the rendered content.
-
-## Security note
-
-The Markdown in documentation comments is placed without processing into
-the final webpage. Be careful with literal HTML:
-
-```rust
-/// <script>alert(document.cookie)</script>
-# fn foo() {}
-```
diff --git a/src/doc/book/src/drop.md b/src/doc/book/src/drop.md
deleted file mode 100644 (file)
index 53c507e..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-# Drop
-
-Now that we’ve discussed traits, let’s talk about a particular trait provided
-by the Rust standard library, [`Drop`][drop]. The `Drop` trait provides a way
-to run some code when a value goes out of scope. For example:
-
-[drop]: ../std/ops/trait.Drop.html
-
-```rust
-struct HasDrop;
-
-impl Drop for HasDrop {
-    fn drop(&mut self) {
-        println!("Dropping!");
-    }
-}
-
-fn main() {
-    let x = HasDrop;
-
-    // Do stuff.
-
-} // `x` goes out of scope here.
-```
-
-When `x` goes out of scope at the end of `main()`, the code for `Drop` will
-run. `Drop` has one method, which is also called `drop()`. It takes a mutable
-reference to `self`.
-
-That’s it! The mechanics of `Drop` are very simple, but there are some
-subtleties. For example, values are dropped in the opposite order they are
-declared. Here’s another example:
-
-```rust
-struct Firework {
-    strength: i32,
-}
-
-impl Drop for Firework {
-    fn drop(&mut self) {
-        println!("BOOM times {}!!!", self.strength);
-    }
-}
-
-fn main() {
-    let firecracker = Firework { strength: 1 };
-    let tnt = Firework { strength: 100 };
-}
-```
-
-This will output:
-
-```text
-BOOM times 100!!!
-BOOM times 1!!!
-```
-
-The `tnt` goes off before the `firecracker` does, because it was declared
-afterwards. Last in, first out.
-
-So what is `Drop` good for? Generally, `Drop` is used to clean up any resources
-associated with a `struct`. For example, the [`Arc<T>` type][arc] is a
-reference-counted type. When `Drop` is called, it will decrement the reference
-count, and if the total number of references is zero, will clean up the
-underlying value.
-
-[arc]: ../std/sync/struct.Arc.html
diff --git a/src/doc/book/src/effective-rust.md b/src/doc/book/src/effective-rust.md
deleted file mode 100644 (file)
index ce2dfe4..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Effective Rust
-
-So you’ve learned how to write some Rust code. But there’s a difference between
-writing *any* Rust code and writing *good* Rust code.
-
-This chapter consists of relatively independent tutorials which show you how to
-take your Rust to the next level. Common patterns and standard library features
-will be introduced. Read these sections in any order of your choosing.
diff --git a/src/doc/book/src/enums.md b/src/doc/book/src/enums.md
deleted file mode 100644 (file)
index 9cf5e6b..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-# Enums
-
-An `enum` in Rust is a type that represents data that is one of
-several possible variants. Each variant in the `enum` can optionally
-have data associated with it:
-
-```rust
-enum Message {
-    Quit,
-    ChangeColor(i32, i32, i32),
-    Move { x: i32, y: i32 },
-    Write(String),
-}
-```
-
-The syntax for defining variants resembles the syntaxes used to define structs:
-you can have variants with no data (like unit-like structs), variants with named
-data, and variants with unnamed data (like tuple structs). Unlike
-separate struct definitions, however, an `enum` is a single type. A
-value of the enum can match any of the variants. For this reason, an
-enum is sometimes called a ‘sum type’: the set of possible values of the
-enum is the sum of the sets of possible values for each variant.
-
-We use the `::` syntax to use the name of each variant: they’re scoped by the name
-of the `enum` itself. This allows both of these to work:
-
-```rust
-# enum Message {
-#     Move { x: i32, y: i32 },
-# }
-let x: Message = Message::Move { x: 3, y: 4 };
-
-enum BoardGameTurn {
-    Move { squares: i32 },
-    Pass,
-}
-
-let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 };
-```
-
-Both variants are named `Move`, but since they’re scoped to the name of
-the enum, they can both be used without conflict.
-
-A value of an `enum` type contains information about which variant it is,
-in addition to any data associated with that variant. This is sometimes
-referred to as a ‘tagged union’, since the data includes a ‘tag’
-indicating what type it is. The compiler uses this information to
-enforce that you’re accessing the data in the enum safely. For instance,
-you can’t simply try to destructure a value as if it were one of the
-possible variants:
-
-```rust,ignore
-fn process_color_change(msg: Message) {
-    let Message::ChangeColor(r, g, b) = msg; // This causes a compile-time error.
-}
-```
-
-Not supporting these operations may seem rather limiting, but it’s a limitation
-which we can overcome. There are two ways: by implementing equality ourselves,
-or by pattern matching variants with [`match`][match] expressions, which you’ll
-learn in the next section. We don’t know enough about Rust to implement
-equality yet, but we’ll find out in the [`traits`][traits] section.
-
-[match]: match.html
-[traits]: traits.html
-
-# Constructors as functions
-
-An `enum` constructor can also be used like a function. For example:
-
-```rust
-# enum Message {
-# Write(String),
-# }
-let m = Message::Write("Hello, world".to_string());
-```
-
-is the same as
-
-```rust
-# enum Message {
-# Write(String),
-# }
-fn foo(x: String) -> Message {
-    Message::Write(x)
-}
-
-let x = foo("Hello, world".to_string());
-```
-
-This is not immediately useful to us, but when we get to
-[`closures`][closures], we’ll talk about passing functions as arguments to
-other functions. For example, with [`iterators`][iterators], we can do this
-to convert a vector of `String`s into a vector of `Message::Write`s:
-
-```rust
-# enum Message {
-# Write(String),
-# }
-
-let v = vec!["Hello".to_string(), "World".to_string()];
-
-let v1: Vec<Message> = v.into_iter().map(Message::Write).collect();
-```
-
-[closures]: closures.html
-[iterators]: iterators.html
diff --git a/src/doc/book/src/error-handling.md b/src/doc/book/src/error-handling.md
deleted file mode 100644 (file)
index c823c32..0000000
+++ /dev/null
@@ -1,2213 +0,0 @@
-# Error Handling
-
-Like most programming languages, Rust encourages the programmer to handle
-errors in a particular way. Generally speaking, error handling is divided into
-two broad categories: exceptions and return values. Rust opts for return
-values.
-
-In this section, we intend to provide a comprehensive treatment of how to deal
-with errors in Rust. More than that, we will attempt to introduce error handling
-one piece at a time so that you'll come away with a solid working knowledge of
-how everything fits together.
-
-When done naïvely, error handling in Rust can be verbose and annoying. This
-section will explore those stumbling blocks and demonstrate how to use the
-standard library to make error handling concise and ergonomic.
-
-# Table of Contents
-
-This section is very long, mostly because we start at the very beginning with
-sum types and combinators, and try to motivate the way Rust does error handling
-incrementally. As such, programmers with experience in other expressive type
-systems may want to jump around.
-
-* [The Basics](#the-basics)
-    * [Unwrapping explained](#unwrapping-explained)
-    * [The `Option` type](#the-option-type)
-        * [Composing `Option<T>` values](#composing-optiont-values)
-    * [The `Result` type](#the-result-type)
-        * [Parsing integers](#parsing-integers)
-        * [The `Result` type alias idiom](#the-result-type-alias-idiom)
-    * [A brief interlude: unwrapping isn't evil](#a-brief-interlude-unwrapping-isnt-evil)
-* [Working with multiple error types](#working-with-multiple-error-types)
-    * [Composing `Option` and `Result`](#composing-option-and-result)
-    * [The limits of combinators](#the-limits-of-combinators)
-    * [Early returns](#early-returns)
-    * [The `try!` macro](#the-try-macro)
-    * [Defining your own error type](#defining-your-own-error-type)
-* [Standard library traits used for error handling](#standard-library-traits-used-for-error-handling)
-    * [The `Error` trait](#the-error-trait)
-    * [The `From` trait](#the-from-trait)
-    * [The real `try!` macro](#the-real-try-macro)
-    * [Composing custom error types](#composing-custom-error-types)
-    * [Advice for library writers](#advice-for-library-writers)
-* [Case study: A program to read population data](#case-study-a-program-to-read-population-data)
-    * [Initial setup](#initial-setup)
-    * [Argument parsing](#argument-parsing)
-    * [Writing the logic](#writing-the-logic)
-    * [Error handling with `Box<Error>`](#error-handling-with-boxerror)
-    * [Reading from stdin](#reading-from-stdin)
-    * [Error handling with a custom type](#error-handling-with-a-custom-type)
-    * [Adding functionality](#adding-functionality)
-* [The short story](#the-short-story)
-
-# The Basics
-
-You can think of error handling as using *case analysis* to determine whether
-a computation was successful or not. As you will see, the key to ergonomic error
-handling is reducing the amount of explicit case analysis the programmer has to
-do while keeping code composable.
-
-Keeping code composable is important, because without that requirement, we
-could [`panic`](../std/macro.panic.html) whenever we
-come across something unexpected. (`panic` causes the current task to unwind,
-and in most cases, the entire program aborts.) Here's an example:
-
-```rust,should_panic
-// Guess a number between 1 and 10.
-// If it matches the number we had in mind, return `true`. Else, return `false`.
-fn guess(n: i32) -> bool {
-    if n < 1 || n > 10 {
-        panic!("Invalid number: {}", n);
-    }
-    n == 5
-}
-
-fn main() {
-    guess(11);
-}
-```
-
-If you try running this code, the program will crash with a message like this:
-
-```text
-thread 'main' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5
-```
-
-Here's another example that is slightly less contrived. A program that accepts
-an integer as an argument, doubles it and prints it.
-
-<span id="code-unwrap-double"></span>
-
-```rust,should_panic
-use std::env;
-
-fn main() {
-    let mut argv = env::args();
-    let arg: String = argv.nth(1).unwrap(); // error 1
-    let n: i32 = arg.parse().unwrap(); // error 2
-    println!("{}", 2 * n);
-}
-```
-
-If you give this program zero arguments (error 1) or if the first argument
-isn't an integer (error 2), the program will panic just like in the first
-example.
-
-You can think of this style of error handling as similar to a bull running
-through a china shop. The bull will get to where it wants to go, but it will
-trample everything in the process.
-
-## Unwrapping explained
-
-In the previous example, we claimed
-that the program would simply panic if it reached one of the two error
-conditions, yet, the program does not include an explicit call to `panic` like
-the first example. This is because the
-panic is embedded in the calls to `unwrap`.
-
-To “unwrap” something in Rust is to say, “Give me the result of the
-computation, and if there was an error, panic and stop the program.”
-It would be better if we showed the code for unwrapping because it is so
-simple, but to do that, we will first need to explore the `Option` and `Result`
-types. Both of these types have a method called `unwrap` defined on them.
-
-### The `Option` type
-
-The `Option` type is [defined in the standard library][5]:
-
-```rust
-enum Option<T> {
-    None,
-    Some(T),
-}
-```
-
-The `Option` type is a way to use Rust's type system to express the
-*possibility of absence*. Encoding the possibility of absence into the type
-system is an important concept because it will cause the compiler to force the
-programmer to handle that absence. Let's take a look at an example that tries
-to find a character in a string:
-
-<span id="code-option-ex-string-find"></span>
-
-```rust
-// Searches `haystack` for the Unicode character `needle`. If one is found, the
-// byte offset of the character is returned. Otherwise, `None` is returned.
-fn find(haystack: &str, needle: char) -> Option<usize> {
-    for (offset, c) in haystack.char_indices() {
-        if c == needle {
-            return Some(offset);
-        }
-    }
-    None
-}
-```
-
-Notice that when this function finds a matching character, it doesn't only
-return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or
-a *value constructor* for the `Option` type. You can think of it as a function
-with the type `fn<T>(value: T) -> Option<T>`. Correspondingly, `None` is also a
-value constructor, except it has no arguments. You can think of `None` as a
-function with the type `fn<T>() -> Option<T>`.
-
-This might seem like much ado about nothing, but this is only half of the
-story. The other half is *using* the `find` function we've written. Let's try
-to use it to find the extension in a file name.
-
-```rust
-# fn find(haystack: &str, needle: char) -> Option<usize> { haystack.find(needle) }
-fn main() {
-    let file_name = "foobar.rs";
-    match find(file_name, '.') {
-        None => println!("No file extension found."),
-        Some(i) => println!("File extension: {}", &file_name[i+1..]),
-    }
-}
-```
-
-This code uses [pattern matching][1] to do *case
-analysis* on the `Option<usize>` returned by the `find` function. In fact, case
-analysis is the only way to get at the value stored inside an `Option<T>`. This
-means that you, as the programmer, must handle the case when an `Option<T>` is
-`None` instead of `Some(t)`.
-
-But wait, what about `unwrap`, which we used [previously](#code-unwrap-double)?
-There was no case analysis there! Instead, the case analysis was put inside the
-`unwrap` method for you. You could define it yourself if you want:
-
-<span id="code-option-def-unwrap"></span>
-
-```rust
-enum Option<T> {
-    None,
-    Some(T),
-}
-
-impl<T> Option<T> {
-    fn unwrap(self) -> T {
-        match self {
-            Option::Some(val) => val,
-            Option::None =>
-              panic!("called `Option::unwrap()` on a `None` value"),
-        }
-    }
-}
-```
-
-The `unwrap` method *abstracts away the case analysis*. This is precisely the thing
-that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that
-`unwrap` is not composable: it is the bull in the china shop.
-
-### Composing `Option<T>` values
-
-In an [example from before](#code-option-ex-string-find),
-we saw how to use `find` to discover the extension in a file name. Of course,
-not all file names have a `.` in them, so it's possible that the file name has
-no extension. This *possibility of absence* is encoded into the types using
-`Option<T>`. In other words, the compiler will force us to address the
-possibility that an extension does not exist. In our case, we only print out a
-message saying as such.
-
-Getting the extension of a file name is a pretty common operation, so it makes
-sense to put it into a function:
-
-```rust
-# fn find(haystack: &str, needle: char) -> Option<usize> { haystack.find(needle) }
-// Returns the extension of the given file name, where the extension is defined
-// as all characters following the first `.`.
-// If `file_name` has no `.`, then `None` is returned.
-fn extension_explicit(file_name: &str) -> Option<&str> {
-    match find(file_name, '.') {
-        None => None,
-        Some(i) => Some(&file_name[i+1..]),
-    }
-}
-```
-
-(Pro-tip: don't use this code. Use the
-[`extension`](../std/path/struct.Path.html#method.extension)
-method in the standard library instead.)
-
-The code stays simple, but the important thing to notice is that the type of
-`find` forces us to consider the possibility of absence. This is a good thing
-because it means the compiler won't let us accidentally forget about the case
-where a file name doesn't have an extension. On the other hand, doing explicit
-case analysis like we've done in `extension_explicit` every time can get a bit
-tiresome.
-
-In fact, the case analysis in `extension_explicit` follows a very common
-pattern: *map* a function on to the value inside of an `Option<T>`, unless the
-option is `None`, in which case, return `None`.
-
-Rust has parametric polymorphism, so it is very easy to define a combinator
-that abstracts this pattern:
-
-<span id="code-option-map"></span>
-
-```rust
-fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A {
-    match option {
-        None => None,
-        Some(value) => Some(f(value)),
-    }
-}
-```
-
-Indeed, `map` is [defined as a method][2] on `Option<T>` in the standard library.
-As a method, it has a slightly different signature: methods take `self`, `&self`,
-or `&mut self` as their first argument.
-
-Armed with our new combinator, we can rewrite our `extension_explicit` method
-to get rid of the case analysis:
-
-```rust
-# fn find(haystack: &str, needle: char) -> Option<usize> { haystack.find(needle) }
-// Returns the extension of the given file name, where the extension is defined
-// as all characters following the first `.`.
-// If `file_name` has no `.`, then `None` is returned.
-fn extension(file_name: &str) -> Option<&str> {
-    find(file_name, '.').map(|i| &file_name[i+1..])
-}
-```
-
-One other pattern we commonly find is assigning a default value to the case
-when an `Option` value is `None`. For example, maybe your program assumes that
-the extension of a file is `rs` even if none is present. As you might imagine,
-the case analysis for this is not specific to file extensions - it can work
-with any `Option<T>`:
-
-```rust
-fn unwrap_or<T>(option: Option<T>, default: T) -> T {
-    match option {
-        None => default,
-        Some(value) => value,
-    }
-}
-```
-
-Like with `map` above, the standard library implementation is a method instead
-of a free function.
-
-The trick here is that the default value must have the same type as the value
-that might be inside the `Option<T>`. Using it is dead simple in our case:
-
-```rust
-# fn find(haystack: &str, needle: char) -> Option<usize> {
-#     for (offset, c) in haystack.char_indices() {
-#         if c == needle {
-#             return Some(offset);
-#         }
-#     }
-#     None
-# }
-#
-# fn extension(file_name: &str) -> Option<&str> {
-#     find(file_name, '.').map(|i| &file_name[i+1..])
-# }
-fn main() {
-    assert_eq!(extension("foobar.csv").unwrap_or("rs"), "csv");
-    assert_eq!(extension("foobar").unwrap_or("rs"), "rs");
-}
-```
-
-(Note that `unwrap_or` is [defined as a method][3] on `Option<T>` in the
-standard library, so we use that here instead of the free-standing function we
-defined above. Don't forget to check out the more general [`unwrap_or_else`][4]
-method.)
-
-There is one more combinator that we think is worth paying special attention to:
-`and_then`. It makes it easy to compose distinct computations that admit the
-*possibility of absence*. For example, much of the code in this section is
-about finding an extension given a file name. In order to do this, you first
-need the file name which is typically extracted from a file *path*. While most
-file paths have a file name, not *all* of them do. For example, `.`, `..` or
-`/`.
-
-So, we are tasked with the challenge of finding an extension given a file
-*path*. Let's start with explicit case analysis:
-
-```rust
-# fn extension(file_name: &str) -> Option<&str> { None }
-fn file_path_ext_explicit(file_path: &str) -> Option<&str> {
-    match file_name(file_path) {
-        None => None,
-        Some(name) => match extension(name) {
-            None => None,
-            Some(ext) => Some(ext),
-        }
-    }
-}
-
-fn file_name(file_path: &str) -> Option<&str> {
-  // Implementation elided.
-  unimplemented!()
-}
-```
-
-You might think that we could use the `map` combinator to reduce the case
-analysis, but its type doesn't quite fit...
-
-```rust,ignore
-fn file_path_ext(file_path: &str) -> Option<&str> {
-    file_name(file_path).map(|x| extension(x)) // This causes a compilation error.
-}
-```
-
-The `map` function here wraps the value returned by the `extension` function
-inside an `Option<_>` and since the `extension` function itself returns an
-`Option<&str>` the expression `file_name(file_path).map(|x| extension(x))`
-actually returns an `Option<Option<&str>>`.
-
-But since `file_path_ext` just returns `Option<&str>` (and not
-`Option<Option<&str>>`) we get a compilation error.
-
-The result of the function taken by map as input is *always* [rewrapped with
-`Some`](#code-option-map). Instead, we need something like `map`, but which
-allows the caller to return a `Option<_>` directly without wrapping it in
-another `Option<_>`.
-
-Its generic implementation is even simpler than `map`:
-
-```rust
-fn and_then<F, T, A>(option: Option<T>, f: F) -> Option<A>
-        where F: FnOnce(T) -> Option<A> {
-    match option {
-        None => None,
-        Some(value) => f(value),
-    }
-}
-```
-
-Now we can rewrite our `file_path_ext` function without explicit case analysis:
-
-```rust
-# fn extension(file_name: &str) -> Option<&str> { None }
-# fn file_name(file_path: &str) -> Option<&str> { None }
-fn file_path_ext(file_path: &str) -> Option<&str> {
-    file_name(file_path).and_then(extension)
-}
-```
-
-Side note: Since `and_then` essentially works like `map` but returns an
-`Option<_>` instead of an `Option<Option<_>>` it is known as `flatmap` in some
-other languages.
-
-The `Option` type has many other combinators [defined in the standard
-library][5]. It is a good idea to skim this list and familiarize
-yourself with what's available—they can often reduce case analysis
-for you. Familiarizing yourself with these combinators will pay
-dividends because many of them are also defined (with similar
-semantics) for `Result`, which we will talk about next.
-
-Combinators make using types like `Option` ergonomic because they reduce
-explicit case analysis. They are also composable because they permit the caller
-to handle the possibility of absence in their own way. Methods like `unwrap`
-remove choices because they will panic if `Option<T>` is `None`.
-
-## The `Result` type
-
-The `Result` type is also
-[defined in the standard library][6]:
-
-<span id="code-result-def"></span>
-
-```rust
-enum Result<T, E> {
-    Ok(T),
-    Err(E),
-}
-```
-
-The `Result` type is a richer version of `Option`. Instead of expressing the
-possibility of *absence* like `Option` does, `Result` expresses the possibility
-of *error*. Usually, the *error* is used to explain why the execution of some
-computation failed. This is a strictly more general form of `Option`. Consider
-the following type alias, which is semantically equivalent to the real
-`Option<T>` in every way:
-
-```rust
-type Option<T> = Result<T, ()>;
-```
-
-This fixes the second type parameter of `Result` to always be `()` (pronounced
-“unit” or “empty tuple”). Exactly one value inhabits the `()` type: `()`. (Yup,
-the type and value level terms have the same notation!)
-
-The `Result` type is a way of representing one of two possible outcomes in a
-computation. By convention, one outcome is meant to be expected or “`Ok`” while
-the other outcome is meant to be unexpected or “`Err`”.
-
-Just like `Option`, the `Result` type also has an
-[`unwrap` method
-defined][7]
-in the standard library. Let's define it:
-
-```rust
-# enum Result<T, E> { Ok(T), Err(E) }
-impl<T, E: ::std::fmt::Debug> Result<T, E> {
-    fn unwrap(self) -> T {
-        match self {
-            Result::Ok(val) => val,
-            Result::Err(err) =>
-              panic!("called `Result::unwrap()` on an `Err` value: {:?}", err),
-        }
-    }
-}
-```
-
-This is effectively the same as our [definition for
-`Option::unwrap`](#code-option-def-unwrap), except it includes the
-error value in the `panic!` message. This makes debugging easier, but
-it also requires us to add a [`Debug`][8] constraint on the `E` type
-parameter (which represents our error type). Since the vast majority
-of types should satisfy the `Debug` constraint, this tends to work out
-in practice. (`Debug` on a type simply means that there's a reasonable
-way to print a human readable description of values with that type.)
-
-OK, let's move on to an example.
-
-### Parsing integers
-
-The Rust standard library makes converting strings to integers dead simple.
-It's so easy in fact, that it is very tempting to write something like the
-following:
-
-```rust
-fn double_number(number_str: &str) -> i32 {
-    2 * number_str.parse::<i32>().unwrap()
-}
-
-fn main() {
-    let n: i32 = double_number("10");
-    assert_eq!(n, 20);
-}
-```
-
-At this point, you should be skeptical of calling `unwrap`. For example, if
-the string doesn't parse as a number, you'll get a panic:
-
-```text
-thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', /home/rustbuild/src/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/result.rs:729
-```
-
-This is rather unsightly, and if this happened inside a library you're
-using, you might be understandably annoyed. Instead, we should try to
-handle the error in our function and let the caller decide what to
-do. This means changing the return type of `double_number`. But to
-what? Well, that requires looking at the signature of the [`parse`
-method][9] in the standard library:
-
-```rust,ignore
-impl str {
-    fn parse<F: FromStr>(&self) -> Result<F, F::Err>;
-}
-```
-
-Hmm. So we at least know that we need to use a `Result`. Certainly, it's
-possible that this could have returned an `Option`. After all, a string either
-parses as a number or it doesn't, right? That's certainly a reasonable way to
-go, but the implementation internally distinguishes *why* the string didn't
-parse as an integer. (Whether it's an empty string, an invalid digit, too big
-or too small.) Therefore, using a `Result` makes sense because we want to
-provide more information than simply “absence.” We want to say *why* the
-parsing failed. You should try to emulate this line of reasoning when faced
-with a choice between `Option` and `Result`. If you can provide detailed error
-information, then you probably should. (We'll see more on this later.)
-
-OK, but how do we write our return type? The `parse` method as defined
-above is generic over all the different number types defined in the
-standard library. We could (and probably should) also make our
-function generic, but let's favor explicitness for the moment. We only
-care about `i32`, so we need to [find its implementation of
-`FromStr`](../std/primitive.i32.html) (do a `CTRL-F` in your browser
-for “FromStr”) and look at its [associated type][10] `Err`. We did
-this so we can find the concrete error type. In this case, it's
-[`std::num::ParseIntError`](../std/num/struct.ParseIntError.html).
-Finally, we can rewrite our function:
-
-```rust
-use std::num::ParseIntError;
-
-fn double_number(number_str: &str) -> Result<i32, ParseIntError> {
-    match number_str.parse::<i32>() {
-        Ok(n) => Ok(2 * n),
-        Err(err) => Err(err),
-    }
-}
-
-fn main() {
-    match double_number("10") {
-        Ok(n) => assert_eq!(n, 20),
-        Err(err) => println!("Error: {:?}", err),
-    }
-}
-```
-
-This is a little better, but now we've written a lot more code! The case
-analysis has once again bitten us.
-
-Combinators to the rescue! Just like `Option`, `Result` has lots of combinators
-defined as methods. There is a large intersection of common combinators between
-`Result` and `Option`. In particular, `map` is part of that intersection:
-
-```rust
-use std::num::ParseIntError;
-
-fn double_number(number_str: &str) -> Result<i32, ParseIntError> {
-    number_str.parse::<i32>().map(|n| 2 * n)
-}
-
-fn main() {
-    match double_number("10") {
-        Ok(n) => assert_eq!(n, 20),
-        Err(err) => println!("Error: {:?}", err),
-    }
-}
-```
-
-The usual suspects are all there for `Result`, including
-[`unwrap_or`](../std/result/enum.Result.html#method.unwrap_or) and
-[`and_then`](../std/result/enum.Result.html#method.and_then).
-Additionally, since `Result` has a second type parameter, there are
-combinators that affect only the error type, such as
-[`map_err`](../std/result/enum.Result.html#method.map_err) (instead of
-`map`) and [`or_else`](../std/result/enum.Result.html#method.or_else)
-(instead of `and_then`).
-
-### The `Result` type alias idiom
-
-In the standard library, you may frequently see types like
-`Result<i32>`. But wait, [we defined `Result`](#code-result-def) to
-have two type parameters. How can we get away with only specifying
-one? The key is to define a `Result` type alias that *fixes* one of
-the type parameters to a particular type. Usually the fixed type is
-the error type. For example, our previous example parsing integers
-could be rewritten like this:
-
-```rust
-use std::num::ParseIntError;
-use std::result;
-
-type Result<T> = result::Result<T, ParseIntError>;
-
-fn double_number(number_str: &str) -> Result<i32> {
-    unimplemented!();
-}
-```
-
-Why would we do this? Well, if we have a lot of functions that could return
-`ParseIntError`, then it's much more convenient to define an alias that always
-uses `ParseIntError` so that we don't have to write it out all the time.
-
-The most prominent place this idiom is used in the standard library is
-with [`io::Result`](../std/io/type.Result.html). Typically, one writes
-`io::Result<T>`, which makes it clear that you're using the `io`
-module's type alias instead of the plain definition from
-`std::result`. (This idiom is also used for
-[`fmt::Result`](../std/fmt/type.Result.html).)
-
-## A brief interlude: unwrapping isn't evil
-
-If you've been following along, you might have noticed that I've taken a pretty
-hard line against calling methods like `unwrap` that could `panic` and abort
-your program. *Generally speaking*, this is good advice.
-
-However, `unwrap` can still be used judiciously. What exactly justifies use of
-`unwrap` is somewhat of a grey area and reasonable people can disagree. I'll
-summarize some of my *opinions* on the matter.
-
-* **In examples and quick 'n' dirty code.** Sometimes you're writing examples
-  or a quick program, and error handling simply isn't important. Beating the
-  convenience of `unwrap` can be hard in such scenarios, so it is very
-  appealing.
-* **When panicking indicates a bug in the program.** When the invariants of
-  your code should prevent a certain case from happening (like, say, popping
-  from an empty stack), then panicking can be permissible. This is because it
-  exposes a bug in your program. This can be explicit, like from an `assert!`
-  failing, or it could be because your index into an array was out of bounds.
-
-This is probably not an exhaustive list. Moreover, when using an
-`Option`, it is often better to use its
-[`expect`](../std/option/enum.Option.html#method.expect)
-method. `expect` does exactly the same thing as `unwrap`, except it
-prints a message you give to `expect`. This makes the resulting panic
-a bit nicer to deal with, since it will show your message instead of
-“called unwrap on a `None` value.”
-
-My advice boils down to this: use good judgment. There's a reason why the words
-“never do X” or “Y is considered harmful” don't appear in my writing. There are
-trade offs to all things, and it is up to you as the programmer to determine
-what is acceptable for your use cases. My goal is only to help you evaluate
-trade offs as accurately as possible.
-
-Now that we've covered the basics of error handling in Rust, and
-explained unwrapping, let's start exploring more of the standard
-library.
-
-# Working with multiple error types
-
-Thus far, we've looked at error handling where everything was either an
-`Option<T>` or a `Result<T, SomeError>`. But what happens when you have both an
-`Option` and a `Result`? Or what if you have a `Result<T, Error1>` and a
-`Result<T, Error2>`? Handling *composition of distinct error types* is the next
-challenge in front of us, and it will be the major theme throughout the rest of
-this section.
-
-## Composing `Option` and `Result`
-
-So far, I've talked about combinators defined for `Option` and combinators
-defined for `Result`. We can use these combinators to compose results of
-different computations without doing explicit case analysis.
-
-Of course, in real code, things aren't always as clean. Sometimes you have a
-mix of `Option` and `Result` types. Must we resort to explicit case analysis,
-or can we continue using combinators?
-
-For now, let's revisit one of the first examples in this section:
-
-```rust,should_panic
-use std::env;
-
-fn main() {
-    let mut argv = env::args();
-    let arg: String = argv.nth(1).unwrap(); // error 1
-    let n: i32 = arg.parse().unwrap(); // error 2
-    println!("{}", 2 * n);
-}
-```
-
-Given our new found knowledge of `Option`, `Result` and their various
-combinators, we should try to rewrite this so that errors are handled properly
-and the program doesn't panic if there's an error.
-
-The tricky aspect here is that `argv.nth(1)` produces an `Option` while
-`arg.parse()` produces a `Result`. These aren't directly composable. When faced
-with both an `Option` and a `Result`, the solution is *usually* to convert the
-`Option` to a `Result`. In our case, the absence of a command line parameter
-(from `env::args()`) means the user didn't invoke the program correctly. We
-could use a `String` to describe the error. Let's try:
-
-<span id="code-error-double-string"></span>
-
-```rust
-use std::env;
-
-fn double_arg(mut argv: env::Args) -> Result<i32, String> {
-    argv.nth(1)
-        .ok_or("Please give at least one argument".to_owned())
-        .and_then(|arg| arg.parse::<i32>().map_err(|err| err.to_string()))
-        .map(|n| 2 * n)
-}
-
-fn main() {
-    match double_arg(env::args()) {
-        Ok(n) => println!("{}", n),
-        Err(err) => println!("Error: {}", err),
-    }
-}
-```
-
-There are a couple new things in this example. The first is the use of the
-[`Option::ok_or`](../std/option/enum.Option.html#method.ok_or)
-combinator. This is one way to convert an `Option` into a `Result`. The
-conversion requires you to specify what error to use if `Option` is `None`.
-Like the other combinators we've seen, its definition is very simple:
-
-```rust
-fn ok_or<T, E>(option: Option<T>, err: E) -> Result<T, E> {
-    match option {
-        Some(val) => Ok(val),
-        None => Err(err),
-    }
-}
-```
-
-The other new combinator used here is
-[`Result::map_err`](../std/result/enum.Result.html#method.map_err).
-This is like `Result::map`, except it maps a function on to the *error*
-portion of a `Result` value. If the `Result` is an `Ok(...)` value, then it is
-returned unmodified.
-
-We use `map_err` here because it is necessary for the error types to remain
-the same (because of our use of `and_then`). Since we chose to convert the
-`Option<String>` (from `argv.nth(1)`) to a `Result<String, String>`, we must
-also convert the `ParseIntError` from `arg.parse()` to a `String`.
-
-## The limits of combinators
-
-Doing IO and parsing input is a very common task, and it's one that I
-personally have done a lot of in Rust. Therefore, we will use (and continue to
-use) IO and various parsing routines to exemplify error handling.
-
-Let's start simple. We are tasked with opening a file, reading all of its
-contents and converting its contents to a number. Then we multiply it by `2`
-and print the output.
-
-Although I've tried to convince you not to use `unwrap`, it can be useful
-to first write your code using `unwrap`. It allows you to focus on your problem
-instead of the error handling, and it exposes the points where proper error
-handling need to occur. Let's start there so we can get a handle on the code,
-and then refactor it to use better error handling.
-
-```rust,should_panic
-use std::fs::File;
-use std::io::Read;
-use std::path::Path;
-
-fn file_double<P: AsRef<Path>>(file_path: P) -> i32 {
-    let mut file = File::open(file_path).unwrap(); // error 1
-    let mut contents = String::new();
-    file.read_to_string(&mut contents).unwrap(); // error 2
-    let n: i32 = contents.trim().parse().unwrap(); // error 3
-    2 * n
-}
-
-fn main() {
-    let doubled = file_double("foobar");
-    println!("{}", doubled);
-}
-```
-
-(N.B. The `AsRef<Path>` is used because those are the
-[same bounds used on
-`std::fs::File::open`](../std/fs/struct.File.html#method.open).
-This makes it ergonomic to use any kind of string as a file path.)
-
-There are three different errors that can occur here:
-
-1. A problem opening the file.
-2. A problem reading data from the file.
-3. A problem parsing the data as a number.
-
-The first two problems are described via the
-[`std::io::Error`](../std/io/struct.Error.html) type. We know this
-because of the return types of
-[`std::fs::File::open`](../std/fs/struct.File.html#method.open) and
-[`std::io::Read::read_to_string`](../std/io/trait.Read.html#method.read_to_string).
-(Note that they both use the [`Result` type alias
-idiom](#the-result-type-alias-idiom) described previously. If you
-click on the `Result` type, you'll [see the type
-alias](../std/io/type.Result.html), and consequently, the underlying
-`io::Error` type.)  The third problem is described by the
-[`std::num::ParseIntError`](../std/num/struct.ParseIntError.html)
-type. The `io::Error` type in particular is *pervasive* throughout the
-standard library. You will see it again and again.
-
-Let's start the process of refactoring the `file_double` function. To make this
-function composable with other components of the program, it should *not* panic
-if any of the above error conditions are met. Effectively, this means that the
-function should *return an error* if any of its operations fail. Our problem is
-that the return type of `file_double` is `i32`, which does not give us any
-useful way of reporting an error. Thus, we must start by changing the return
-type from `i32` to something else.
-
-The first thing we need to decide: should we use `Option` or `Result`? We
-certainly could use `Option` very easily. If any of the three errors occur, we
-could simply return `None`. This will work *and it is better than panicking*,
-but we can do a lot better. Instead, we should pass some detail about the error
-that occurred. Since we want to express the *possibility of error*, we should
-use `Result<i32, E>`. But what should `E` be? Since two *different* types of
-errors can occur, we need to convert them to a common type. One such type is
-`String`. Let's see how that impacts our code:
-
-```rust
-use std::fs::File;
-use std::io::Read;
-use std::path::Path;
-
-fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
-    File::open(file_path)
-         .map_err(|err| err.to_string())
-         .and_then(|mut file| {
-              let mut contents = String::new();
-              file.read_to_string(&mut contents)
-                  .map_err(|err| err.to_string())
-                  .map(|_| contents)
-         })
-         .and_then(|contents| {
-              contents.trim().parse::<i32>()
-                      .map_err(|err| err.to_string())
-         })
-         .map(|n| 2 * n)
-}
-
-fn main() {
-    match file_double("foobar") {
-        Ok(n) => println!("{}", n),
-        Err(err) => println!("Error: {}", err),
-    }
-}
-```
-
-This code looks a bit hairy. It can take quite a bit of practice before code
-like this becomes easy to write. The way we write it is by *following the
-types*. As soon as we changed the return type of `file_double` to
-`Result<i32, String>`, we had to start looking for the right combinators. In
-this case, we only used three different combinators: `and_then`, `map` and
-`map_err`.
-
-`and_then` is used to chain multiple computations where each computation could
-return an error. After opening the file, there are two more computations that
-could fail: reading from the file and parsing the contents as a number.
-Correspondingly, there are two calls to `and_then`.
-
-`map` is used to apply a function to the `Ok(...)` value of a `Result`. For
-example, the very last call to `map` multiplies the `Ok(...)` value (which is
-an `i32`) by `2`. If an error had occurred before that point, this operation
-would have been skipped because of how `map` is defined.
-
-`map_err` is the trick that makes all of this work. `map_err` is like
-`map`, except it applies a function to the `Err(...)` value of a `Result`. In
-this case, we want to convert all of our errors to one type: `String`. Since
-both `io::Error` and `num::ParseIntError` implement `ToString`, we can call the
-`to_string()` method to convert them.
-
-With all of that said, the code is still hairy. Mastering use of combinators is
-important, but they have their limits. Let's try a different approach: early
-returns.
-
-## Early returns
-
-I'd like to take the code from the previous section and rewrite it using *early
-returns*. Early returns let you exit the function early. We can't return early
-in `file_double` from inside another closure, so we'll need to revert back to
-explicit case analysis.
-
-```rust
-use std::fs::File;
-use std::io::Read;
-use std::path::Path;
-
-fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
-    let mut file = match File::open(file_path) {
-        Ok(file) => file,
-        Err(err) => return Err(err.to_string()),
-    };
-    let mut contents = String::new();
-    if let Err(err) = file.read_to_string(&mut contents) {
-        return Err(err.to_string());
-    }
-    let n: i32 = match contents.trim().parse() {
-        Ok(n) => n,
-        Err(err) => return Err(err.to_string()),
-    };
-    Ok(2 * n)
-}
-
-fn main() {
-    match file_double("foobar") {
-        Ok(n) => println!("{}", n),
-        Err(err) => println!("Error: {}", err),
-    }
-}
-```
-
-Reasonable people can disagree over whether this code is better than the code
-that uses combinators, but if you aren't familiar with the combinator approach,
-this code looks simpler to read to me. It uses explicit case analysis with
-`match` and `if let`. If an error occurs, it simply stops executing the
-function and returns the error (by converting it to a string).
-
-Isn't this a step backwards though? Previously, we said that the key to
-ergonomic error handling is reducing explicit case analysis, yet we've reverted
-back to explicit case analysis here. It turns out, there are *multiple* ways to
-reduce explicit case analysis. Combinators aren't the only way.
-
-## The `try!` macro
-
-A cornerstone of error handling in Rust is the `try!` macro. The `try!` macro
-abstracts case analysis like combinators, but unlike combinators, it also
-abstracts *control flow*. Namely, it can abstract the *early return* pattern
-seen above.
-
-Here is a simplified definition of a `try!` macro:
-
-<span id="code-try-def-simple"></span>
-
-```rust
-macro_rules! try {
-    ($e:expr) => (match $e {
-        Ok(val) => val,
-        Err(err) => return Err(err),
-    });
-}
-```
-
-(The [real definition](../std/macro.try.html) is a bit more
-sophisticated. We will address that later.)
-
-Using the `try!` macro makes it very easy to simplify our last example. Since
-it does the case analysis and the early return for us, we get tighter code that
-is easier to read:
-
-```rust
-use std::fs::File;
-use std::io::Read;
-use std::path::Path;
-
-fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
-    let mut file = try!(File::open(file_path).map_err(|e| e.to_string()));
-    let mut contents = String::new();
-    try!(file.read_to_string(&mut contents).map_err(|e| e.to_string()));
-    let n = try!(contents.trim().parse::<i32>().map_err(|e| e.to_string()));
-    Ok(2 * n)
-}
-
-fn main() {
-    match file_double("foobar") {
-        Ok(n) => println!("{}", n),
-        Err(err) => println!("Error: {}", err),
-    }
-}
-```
-
-The `map_err` calls are still necessary given
-[our definition of `try!`](#code-try-def-simple).
-This is because the error types still need to be converted to `String`.
-The good news is that we will soon learn how to remove those `map_err` calls!
-The bad news is that we will need to learn a bit more about a couple important
-traits in the standard library before we can remove the `map_err` calls.
-
-## Defining your own error type
-
-Before we dive into some of the standard library error traits, I'd like to wrap
-up this section by removing the use of `String` as our error type in the
-previous examples.
-
-Using `String` as we did in our previous examples is convenient because it's
-easy to convert errors to strings, or even make up your own errors as strings
-on the spot. However, using `String` for your errors has some downsides.
-
-The first downside is that the error messages tend to clutter your
-code. It's possible to define the error messages elsewhere, but unless
-you're unusually disciplined, it is very tempting to embed the error
-message into your code. Indeed, we did exactly this in a [previous
-example](#code-error-double-string).
-
-The second and more important downside is that `String`s are *lossy*. That is,
-if all errors are converted to strings, then the errors we pass to the caller
-become completely opaque. The only reasonable thing the caller can do with a
-`String` error is show it to the user. Certainly, inspecting the string to
-determine the type of error is not robust. (Admittedly, this downside is far
-more important inside of a library as opposed to, say, an application.)
-
-For example, the `io::Error` type embeds an
-[`io::ErrorKind`](../std/io/enum.ErrorKind.html),
-which is *structured data* that represents what went wrong during an IO
-operation. This is important because you might want to react differently
-depending on the error. (e.g., A `BrokenPipe` error might mean quitting your
-program gracefully while a `NotFound` error might mean exiting with an error
-code and showing an error to the user.) With `io::ErrorKind`, the caller can
-examine the type of an error with case analysis, which is strictly superior
-to trying to tease out the details of an error inside of a `String`.
-
-Instead of using a `String` as an error type in our previous example of reading
-an integer from a file, we can define our own error type that represents errors
-with *structured data*. We endeavor to not drop information from underlying
-errors in case the caller wants to inspect the details.
-
-The ideal way to represent *one of many possibilities* is to define our own
-sum type using `enum`. In our case, an error is either an `io::Error` or a
-`num::ParseIntError`, so a natural definition arises:
-
-```rust
-use std::io;
-use std::num;
-
-// We derive `Debug` because all types should probably derive `Debug`.
-// This gives us a reasonable human readable description of `CliError` values.
-#[derive(Debug)]
-enum CliError {
-    Io(io::Error),
-    Parse(num::ParseIntError),
-}
-```
-
-Tweaking our code is very easy. Instead of converting errors to strings, we
-simply convert them to our `CliError` type using the corresponding value
-constructor:
-
-```rust
-# #[derive(Debug)]
-# enum CliError { Io(::std::io::Error), Parse(::std::num::ParseIntError) }
-use std::fs::File;
-use std::io::Read;
-use std::path::Path;
-
-fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> {
-    let mut file = try!(File::open(file_path).map_err(CliError::Io));
-    let mut contents = String::new();
-    try!(file.read_to_string(&mut contents).map_err(CliError::Io));
-    let n: i32 = try!(contents.trim().parse().map_err(CliError::Parse));
-    Ok(2 * n)
-}
-
-fn main() {
-    match file_double("foobar") {
-        Ok(n) => println!("{}", n),
-        Err(err) => println!("Error: {:?}", err),
-    }
-}
-```
-
-The only change here is switching `map_err(|e| e.to_string())` (which converts
-errors to strings) to `map_err(CliError::Io)` or `map_err(CliError::Parse)`.
-The *caller* gets to decide the level of detail to report to the user. In
-effect, using a `String` as an error type removes choices from the caller while
-using a custom `enum` error type like `CliError` gives the caller all of the
-conveniences as before in addition to *structured data* describing the error.
-
-A rule of thumb is to define your own error type, but a `String` error type
-will do in a pinch, particularly if you're writing an application. If you're
-writing a library, defining your own error type should be strongly preferred so
-that you don't remove choices from the caller unnecessarily.
-
-# Standard library traits used for error handling
-
-The standard library defines two integral traits for error handling:
-[`std::error::Error`](../std/error/trait.Error.html) and
-[`std::convert::From`](../std/convert/trait.From.html). While `Error`
-is designed specifically for generically describing errors, the `From`
-trait serves a more general role for converting values between two
-distinct types.
-
-## The `Error` trait
-
-The `Error` trait is [defined in the standard
-library](../std/error/trait.Error.html):
-
-```rust
-use std::fmt::{Debug, Display};
-
-trait Error: Debug + Display {
-  /// A short description of the error.
-  fn description(&self) -> &str;
-
-  /// The lower level cause of this error, if any.
-  fn cause(&self) -> Option<&Error> { None }
-}
-```
-
-This trait is super generic because it is meant to be implemented for *all*
-types that represent errors. This will prove useful for writing composable code
-as we'll see later. Otherwise, the trait allows you to do at least the
-following things:
-
-* Obtain a `Debug` representation of the error.
-* Obtain a user-facing `Display` representation of the error.
-* Obtain a short description of the error (via the `description` method).
-* Inspect the causal chain of an error, if one exists (via the `cause` method).
-
-The first two are a result of `Error` requiring impls for both `Debug` and
-`Display`. The latter two are from the two methods defined on `Error`. The
-power of `Error` comes from the fact that all error types impl `Error`, which
-means errors can be existentially quantified as a
-[trait object](../book/trait-objects.html).
-This manifests as either `Box<Error>` or `&Error`. Indeed, the `cause` method
-returns an `&Error`, which is itself a trait object. We'll revisit the
-`Error` trait's utility as a trait object later.
-
-For now, it suffices to show an example implementing the `Error` trait. Let's
-use the error type we defined in the
-[previous section](#defining-your-own-error-type):
-
-```rust
-use std::io;
-use std::num;
-
-// We derive `Debug` because all types should probably derive `Debug`.
-// This gives us a reasonable human readable description of `CliError` values.
-#[derive(Debug)]
-enum CliError {
-    Io(io::Error),
-    Parse(num::ParseIntError),
-}
-```
-
-This particular error type represents the possibility of two types of errors
-occurring: an error dealing with I/O or an error converting a string to a
-number. The error could represent as many error types as you want by adding new
-variants to the `enum` definition.
-
-Implementing `Error` is pretty straight-forward. It's mostly going to be a lot
-explicit case analysis.
-
-```rust,ignore
-use std::error;
-use std::fmt;
-
-impl fmt::Display for CliError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            // Both underlying errors already impl `Display`, so we defer to
-            // their implementations.
-            CliError::Io(ref err) => write!(f, "IO error: {}", err),
-            CliError::Parse(ref err) => write!(f, "Parse error: {}", err),
-        }
-    }
-}
-
-impl error::Error for CliError {
-    fn description(&self) -> &str {
-        // Both underlying errors already impl `Error`, so we defer to their
-        // implementations.
-        match *self {
-            CliError::Io(ref err) => err.description(),
-            CliError::Parse(ref err) => err.description(),
-        }
-    }
-
-    fn cause(&self) -> Option<&error::Error> {
-        match *self {
-            // N.B. Both of these implicitly cast `err` from their concrete
-            // types (either `&io::Error` or `&num::ParseIntError`)
-            // to a trait object `&Error`. This works because both error types
-            // implement `Error`.
-            CliError::Io(ref err) => Some(err),
-            CliError::Parse(ref err) => Some(err),
-        }
-    }
-}
-```
-
-We note that this is a very typical implementation of `Error`: match on your
-different error types and satisfy the contracts defined for `description` and
-`cause`.
-
-## The `From` trait
-
-The `std::convert::From` trait is
-[defined in the standard
-library](../std/convert/trait.From.html):
-
-<span id="code-from-def"></span>
-
-```rust
-trait From<T> {
-    fn from(T) -> Self;
-}
-```
-
-Deliciously simple, yes? `From` is very useful because it gives us a generic
-way to talk about conversion *from* a particular type `T` to some other type
-(in this case, “some other type” is the subject of the impl, or `Self`).
-The crux of `From` is the
-[set of implementations provided by the standard
-library](../std/convert/trait.From.html).
-
-Here are a few simple examples demonstrating how `From` works:
-
-```rust
-let string: String = From::from("foo");
-let bytes: Vec<u8> = From::from("foo");
-let cow: ::std::borrow::Cow<str> = From::from("foo");
-```
-
-OK, so `From` is useful for converting between strings. But what about errors?
-It turns out, there is one critical impl:
-
-```rust,ignore
-impl<'a, E: Error + 'a> From<E> for Box<Error + 'a>
-```
-
-This impl says that for *any* type that impls `Error`, we can convert it to a
-trait object `Box<Error>`. This may not seem terribly surprising, but it is
-useful in a generic context.
-
-Remember the two errors we were dealing with previously? Specifically,
-`io::Error` and `num::ParseIntError`. Since both impl `Error`, they work with
-`From`:
-
-```rust
-use std::error::Error;
-use std::fs;
-use std::io;
-use std::num;
-
-// We have to jump through some hoops to actually get error values:
-let io_err: io::Error = io::Error::last_os_error();
-let parse_err: num::ParseIntError = "not a number".parse::<i32>().unwrap_err();
-
-// OK, here are the conversions:
-let err1: Box<Error> = From::from(io_err);
-let err2: Box<Error> = From::from(parse_err);
-```
-
-There is a really important pattern to recognize here. Both `err1` and `err2`
-have the *same type*. This is because they are existentially quantified types,
-or trait objects. In particular, their underlying type is *erased* from the
-compiler's knowledge, so it truly sees `err1` and `err2` as exactly the same.
-Additionally, we constructed `err1` and `err2` using precisely the same
-function call: `From::from`. This is because `From::from` is overloaded on both
-its argument and its return type.
-
-This pattern is important because it solves a problem we had earlier: it gives
-us a way to reliably convert errors to the same type using the same function.
-
-Time to revisit an old friend; the `try!` macro.
-
-## The real `try!` macro
-
-Previously, we presented this definition of `try!`:
-
-```rust
-macro_rules! try {
-    ($e:expr) => (match $e {
-        Ok(val) => val,
-        Err(err) => return Err(err),
-    });
-}
-```
-
-This is not its real definition. Its real definition is
-[in the standard library](../std/macro.try.html):
-
-<span id="code-try-def"></span>
-
-```rust
-macro_rules! try {
-    ($e:expr) => (match $e {
-        Ok(val) => val,
-        Err(err) => return Err(::std::convert::From::from(err)),
-    });
-}
-```
-
-There's one tiny but powerful change: the error value is passed through
-`From::from`. This makes the `try!` macro a lot more powerful because it gives
-you automatic type conversion for free.
-
-Armed with our more powerful `try!` macro, let's take a look at code we wrote
-previously to read a file and convert its contents to an integer:
-
-```rust
-use std::fs::File;
-use std::io::Read;
-use std::path::Path;
-
-fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
-    let mut file = try!(File::open(file_path).map_err(|e| e.to_string()));
-    let mut contents = String::new();
-    try!(file.read_to_string(&mut contents).map_err(|e| e.to_string()));
-    let n = try!(contents.trim().parse::<i32>().map_err(|e| e.to_string()));
-    Ok(2 * n)
-}
-```
-
-Earlier, we promised that we could get rid of the `map_err` calls. Indeed, all
-we have to do is pick a type that `From` works with. As we saw in the previous
-section, `From` has an impl that lets it convert any error type into a
-`Box<Error>`:
-
-```rust
-use std::error::Error;
-use std::fs::File;
-use std::io::Read;
-use std::path::Path;
-
-fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, Box<Error>> {
-    let mut file = try!(File::open(file_path));
-    let mut contents = String::new();
-    try!(file.read_to_string(&mut contents));
-    let n = try!(contents.trim().parse::<i32>());
-    Ok(2 * n)
-}
-```
-
-We are getting very close to ideal error handling. Our code has very little
-overhead as a result from error handling because the `try!` macro encapsulates
-three things simultaneously:
-
-1. Case analysis.
-2. Control flow.
-3. Error type conversion.
-
-When all three things are combined, we get code that is unencumbered by
-combinators, calls to `unwrap` or case analysis.
-
-There's one little nit left: the `Box<Error>` type is *opaque*. If we
-return a `Box<Error>` to the caller, the caller can't (easily) inspect
-underlying error type. The situation is certainly better than `String`
-because the caller can call methods like
-[`description`](../std/error/trait.Error.html#tymethod.description)
-and [`cause`](../std/error/trait.Error.html#method.cause), but the
-limitation remains: `Box<Error>` is opaque. (N.B. This isn't entirely
-true because Rust does have runtime reflection, which is useful in
-some scenarios that are [beyond the scope of this
-section](https://crates.io/crates/error).)
-
-It's time to revisit our custom `CliError` type and tie everything together.
-
-## Composing custom error types
-
-In the last section, we looked at the real `try!` macro and how it does
-automatic type conversion for us by calling `From::from` on the error value.
-In particular, we converted errors to `Box<Error>`, which works, but the type
-is opaque to callers.
-
-To fix this, we use the same remedy that we're already familiar with: a custom
-error type. Once again, here is the code that reads the contents of a file and
-converts it to an integer:
-
-```rust
-use std::fs::File;
-use std::io::{self, Read};
-use std::num;
-use std::path::Path;
-
-// We derive `Debug` because all types should probably derive `Debug`.
-// This gives us a reasonable human readable description of `CliError` values.
-#[derive(Debug)]
-enum CliError {
-    Io(io::Error),
-    Parse(num::ParseIntError),
-}
-
-fn file_double_verbose<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> {
-    let mut file = try!(File::open(file_path).map_err(CliError::Io));
-    let mut contents = String::new();
-    try!(file.read_to_string(&mut contents).map_err(CliError::Io));
-    let n: i32 = try!(contents.trim().parse().map_err(CliError::Parse));
-    Ok(2 * n)
-}
-```
-
-Notice that we still have the calls to `map_err`. Why? Well, recall the
-definitions of [`try!`](#code-try-def) and [`From`](#code-from-def). The
-problem is that there is no `From` impl that allows us to convert from error
-types like `io::Error` and `num::ParseIntError` to our own custom `CliError`.
-Of course, it is easy to fix this! Since we defined `CliError`, we can impl
-`From` with it:
-
-```rust
-# #[derive(Debug)]
-# enum CliError { Io(io::Error), Parse(num::ParseIntError) }
-use std::io;
-use std::num;
-
-impl From<io::Error> for CliError {
-    fn from(err: io::Error) -> CliError {
-        CliError::Io(err)
-    }
-}
-
-impl From<num::ParseIntError> for CliError {
-    fn from(err: num::ParseIntError) -> CliError {
-        CliError::Parse(err)
-    }
-}
-```
-
-All these impls are doing is teaching `From` how to create a `CliError` from
-other error types. In our case, construction is as simple as invoking the
-corresponding value constructor. Indeed, it is *typically* this easy.
-
-We can finally rewrite `file_double`:
-
-```rust
-# use std::io;
-# use std::num;
-# enum CliError { Io(::std::io::Error), Parse(::std::num::ParseIntError) }
-# impl From<io::Error> for CliError {
-#     fn from(err: io::Error) -> CliError { CliError::Io(err) }
-# }
-# impl From<num::ParseIntError> for CliError {
-#     fn from(err: num::ParseIntError) -> CliError { CliError::Parse(err) }
-# }
-
-use std::fs::File;
-use std::io::Read;
-use std::path::Path;
-
-fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> {
-    let mut file = try!(File::open(file_path));
-    let mut contents = String::new();
-    try!(file.read_to_string(&mut contents));
-    let n: i32 = try!(contents.trim().parse());
-    Ok(2 * n)
-}
-```
-
-The only thing we did here was remove the calls to `map_err`. They are no
-longer needed because the `try!` macro invokes `From::from` on the error value.
-This works because we've provided `From` impls for all the error types that
-could appear.
-
-If we modified our `file_double` function to perform some other operation, say,
-convert a string to a float, then we'd need to add a new variant to our error
-type:
-
-```rust
-use std::io;
-use std::num;
-
-enum CliError {
-    Io(io::Error),
-    ParseInt(num::ParseIntError),
-    ParseFloat(num::ParseFloatError),
-}
-```
-
-And add a new `From` impl:
-
-```rust
-# enum CliError {
-#     Io(::std::io::Error),
-#     ParseInt(num::ParseIntError),
-#     ParseFloat(num::ParseFloatError),
-# }
-
-use std::num;
-
-impl From<num::ParseFloatError> for CliError {
-    fn from(err: num::ParseFloatError) -> CliError {
-        CliError::ParseFloat(err)
-    }
-}
-```
-
-And that's it!
-
-## Advice for library writers
-
-If your library needs to report custom errors, then you should
-probably define your own error type. It's up to you whether or not to
-expose its representation (like
-[`ErrorKind`](../std/io/enum.ErrorKind.html)) or keep it hidden (like
-[`ParseIntError`](../std/num/struct.ParseIntError.html)). Regardless
-of how you do it, it's usually good practice to at least provide some
-information about the error beyond its `String`
-representation. But certainly, this will vary depending on use cases.
-
-At a minimum, you should probably implement the
-[`Error`](../std/error/trait.Error.html)
-trait. This will give users of your library some minimum flexibility for
-[composing errors](#the-real-try-macro). Implementing the `Error` trait also
-means that users are guaranteed the ability to obtain a string representation
-of an error (because it requires impls for both `fmt::Debug` and
-`fmt::Display`).
-
-Beyond that, it can also be useful to provide implementations of `From` on your
-error types. This allows you (the library author) and your users to
-[compose more detailed errors](#composing-custom-error-types). For example,
-[`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html)
-provides `From` impls for both `io::Error` and `byteorder::Error`.
-
-Finally, depending on your tastes, you may also want to define a
-[`Result` type alias](#the-result-type-alias-idiom), particularly if your
-library defines a single error type. This is used in the standard library
-for [`io::Result`](../std/io/type.Result.html)
-and [`fmt::Result`](../std/fmt/type.Result.html).
-
-# Case study: A program to read population data
-
-This section was long, and depending on your background, it might be
-rather dense. While there is plenty of example code to go along with
-the prose, most of it was specifically designed to be pedagogical. So,
-we're going to do something new: a case study.
-
-For this, we're going to build up a command line program that lets you
-query world population data. The objective is simple: you give it a location
-and it will tell you the population. Despite the simplicity, there is a lot
-that can go wrong!
-
-The data we'll be using comes from the [Data Science
-Toolkit][11]. I've prepared some data from it for this exercise. You
-can either grab the [world population data][12] (41MB gzip compressed,
-145MB uncompressed) or only the [US population data][13] (2.2MB gzip
-compressed, 7.2MB uncompressed).
-
-Up until now, we've kept the code limited to Rust's standard library. For a real
-task like this though, we'll want to at least use something to parse CSV data,
-parse the program arguments and decode that stuff into Rust types automatically. For that, we'll use the
-[`csv`](https://crates.io/crates/csv),
-and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.
-
-## Initial setup
-
-We're not going to spend a lot of time on setting up a project with
-Cargo because it is already covered well in [the Cargo
-section](getting-started.html#hello-cargo) and [Cargo's documentation][14].
-
-To get started from scratch, run `cargo new --bin city-pop` and make sure your
-`Cargo.toml` looks something like this:
-
-```text
-[package]
-name = "city-pop"
-version = "0.1.0"
-authors = ["Andrew Gallant <jamslam@gmail.com>"]
-
-[[bin]]
-name = "city-pop"
-
-[dependencies]
-csv = "0.*"
-rustc-serialize = "0.*"
-getopts = "0.*"
-```
-
-You should already be able to run:
-
-```text
-cargo build --release
-./target/release/city-pop
-# Outputs: Hello, world!
-```
-
-## Argument parsing
-
-Let's get argument parsing out of the way. We won't go into too much
-detail on Getopts, but there is [some good documentation][15]
-describing it. The short story is that Getopts generates an argument
-parser and a help message from a vector of options (The fact that it
-is a vector is hidden behind a struct and a set of methods). Once the
-parsing is done, the parser returns a struct that records matches
-for defined options, and remaining "free" arguments.
-From there, we can get information about the flags, for
-instance, whether they were passed in, and what arguments they
-had. Here's our program with the appropriate `extern crate`
-statements, and the basic argument setup for Getopts:
-
-```rust,ignore
-extern crate getopts;
-extern crate rustc_serialize;
-
-use getopts::Options;
-use std::env;
-
-fn print_usage(program: &str, opts: Options) {
-    println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program)));
-}
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    let program = &args[0];
-
-    let mut opts = Options::new();
-    opts.optflag("h", "help", "Show this usage message.");
-
-    let matches = match opts.parse(&args[1..]) {
-        Ok(m)  => { m }
-        Err(e) => { panic!(e.to_string()) }
-    };
-    if matches.opt_present("h") {
-        print_usage(&program, opts);
-        return;
-    }
-    let data_path = &matches.free[0];
-    let city: &str = &matches.free[1];
-
-    // Do stuff with information.
-}
-```
-
-First, we get a vector of the arguments passed into our program. We
-then store the first one, knowing that it is our program's name. Once
-that's done, we set up our argument flags, in this case a simplistic
-help message flag. Once we have the argument flags set up, we use
-`Options.parse` to parse the argument vector (starting from index one,
-because index 0 is the program name). If this was successful, we
-assign matches to the parsed object, if not, we panic. Once past that,
-we test if the user passed in the help flag, and if so print the usage
-message. The option help messages are constructed by Getopts, so all
-we have to do to print the usage message is tell it what we want it to
-print for the program name and template. If the user has not passed in
-the help flag, we assign the proper variables to their corresponding
-arguments.
-
-## Writing the logic
-
-We all write code differently, but error handling is usually the last thing we
-want to think about. This isn't great for the overall design of a program, but
-it can be useful for rapid prototyping. Because Rust forces us to be explicit
-about error handling (by making us call `unwrap`), it is easy to see which
-parts of our program can cause errors.
-
-In this case study, the logic is really simple. All we need to do is parse the
-CSV data given to us and print out a field in matching rows. Let's do it. (Make
-sure to add `extern crate csv;` to the top of your file.)
-
-```rust,ignore
-use std::fs::File;
-
-// This struct represents the data in each row of the CSV file.
-// Type based decoding absolves us of a lot of the nitty gritty error
-// handling, like parsing strings as integers or floats.
-#[derive(Debug, RustcDecodable)]
-struct Row {
-    country: String,
-    city: String,
-    accent_city: String,
-    region: String,
-
-    // Not every row has data for the population, latitude or longitude!
-    // So we express them as `Option` types, which admits the possibility of
-    // absence. The CSV parser will fill in the correct value for us.
-    population: Option<u64>,
-    latitude: Option<f64>,
-    longitude: Option<f64>,
-}
-
-fn print_usage(program: &str, opts: Options) {
-    println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program)));
-}
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    let program = &args[0];
-
-    let mut opts = Options::new();
-    opts.optflag("h", "help", "Show this usage message.");
-
-    let matches = match opts.parse(&args[1..]) {
-        Ok(m)  => { m }
-        Err(e) => { panic!(e.to_string()) }
-    };
-
-    if matches.opt_present("h") {
-        print_usage(&program, opts);
-        return;
-    }
-
-    let data_path = &matches.free[0];
-    let city: &str = &matches.free[1];
-
-    let file = File::open(data_path).unwrap();
-    let mut rdr = csv::Reader::from_reader(file);
-
-    for row in rdr.decode::<Row>() {
-        let row = row.unwrap();
-
-        if row.city == city {
-            println!("{}, {}: {:?}",
-                row.city, row.country,
-                row.population.expect("population count"));
-        }
-    }
-}
-```
-
-Let's outline the errors. We can start with the obvious: the three places that
-`unwrap` is called:
-
-1. [`File::open`](../std/fs/struct.File.html#method.open)
-   can return an
-   [`io::Error`](../std/io/struct.Error.html).
-2. [`csv::Reader::decode`](http://burntsushi.net/rustdoc/csv/struct.Reader.html#method.decode)
-   decodes one record at a time, and
-   [decoding a
-   record](http://burntsushi.net/rustdoc/csv/struct.DecodedRecords.html)
-   (look at the `Item` associated type on the `Iterator` impl)
-   can produce a
-   [`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html).
-3. If `row.population` is `None`, then calling `expect` will panic.
-
-Are there any others? What if we can't find a matching city? Tools like `grep`
-will return an error code, so we probably should too. So we have logic errors
-specific to our problem, IO errors and CSV parsing errors. We're going to
-explore two different ways to approach handling these errors.
-
-I'd like to start with `Box<Error>`. Later, we'll see how defining our own
-error type can be useful.
-
-## Error handling with `Box<Error>`
-
-`Box<Error>` is nice because it *just works*. You don't need to define your own
-error types and you don't need any `From` implementations. The downside is that
-since `Box<Error>` is a trait object, it *erases the type*, which means the
-compiler can no longer reason about its underlying type.
-
-[Previously](#the-limits-of-combinators) we started refactoring our code by
-changing the type of our function from `T` to `Result<T, OurErrorType>`. In
-this case, `OurErrorType` is only `Box<Error>`. But what's `T`? And can we add
-a return type to `main`?
-
-The answer to the second question is no, we can't. That means we'll need to
-write a new function. But what is `T`? The simplest thing we can do is to
-return a list of matching `Row` values as a `Vec<Row>`. (Better code would
-return an iterator, but that is left as an exercise to the reader.)
-
-Let's refactor our code into its own function, but keep the calls to `unwrap`.
-Note that we opt to handle the possibility of a missing population count by
-simply ignoring that row.
-
-```rust,ignore
-use std::path::Path;
-
-struct Row {
-    // This struct remains unchanged.
-}
-
-struct PopulationCount {
-    city: String,
-    country: String,
-    // This is no longer an `Option` because values of this type are only
-    // constructed if they have a population count.
-    count: u64,
-}
-
-fn print_usage(program: &str, opts: Options) {
-    println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program)));
-}
-
-fn search<P: AsRef<Path>>(file_path: P, city: &str) -> Vec<PopulationCount> {
-    let mut found = vec![];
-    let file = File::open(file_path).unwrap();
-    let mut rdr = csv::Reader::from_reader(file);
-    for row in rdr.decode::<Row>() {
-        let row = row.unwrap();
-        match row.population {
-            None => { } // Skip it.
-            Some(count) => if row.city == city {
-                found.push(PopulationCount {
-                    city: row.city,
-                    country: row.country,
-                    count: count,
-                });
-            },
-        }
-    }
-    found
-}
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    let program = &args[0];
-
-    let mut opts = Options::new();
-    opts.optflag("h", "help", "Show this usage message.");
-
-    let matches = match opts.parse(&args[1..]) {
-        Ok(m)  => { m }
-        Err(e) => { panic!(e.to_string()) }
-    };
-
-    if matches.opt_present("h") {
-        print_usage(&program, opts);
-        return;
-    }
-
-    let data_path = &matches.free[0];
-    let city: &str = &matches.free[1];
-
-    for pop in search(data_path, city) {
-        println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
-    }
-}
-
-```
-
-While we got rid of one use of `expect` (which is a nicer variant of `unwrap`),
-we still should handle the absence of any search results.
-
-To convert this to proper error handling, we need to do the following:
-
-1. Change the return type of `search` to be `Result<Vec<PopulationCount>,
-   Box<Error>>`.
-2. Use the [`try!` macro](#code-try-def) so that errors are returned to the
-   caller instead of panicking the program.
-3. Handle the error in `main`.
-
-Let's try it:
-
-```rust,ignore
-use std::error::Error;
-
-// The rest of the code before this is unchanged.
-
-fn search<P: AsRef<Path>>
-         (file_path: P, city: &str)
-         -> Result<Vec<PopulationCount>, Box<Error>> {
-    let mut found = vec![];
-    let file = try!(File::open(file_path));
-    let mut rdr = csv::Reader::from_reader(file);
-    for row in rdr.decode::<Row>() {
-        let row = try!(row);
-        match row.population {
-            None => { } // Skip it.
-            Some(count) => if row.city == city {
-                found.push(PopulationCount {
-                    city: row.city,
-                    country: row.country,
-                    count: count,
-                });
-            },
-        }
-    }
-    if found.is_empty() {
-        Err(From::from("No matching cities with a population were found."))
-    } else {
-        Ok(found)
-    }
-}
-```
-
-Instead of `x.unwrap()`, we now have `try!(x)`. Since our function returns a
-`Result<T, E>`, the `try!` macro will return early from the function if an
-error occurs.
-
-At the end of `search` we also convert a plain string to an error type 
-by using the [corresponding `From` impls](../std/convert/trait.From.html):
-
-```rust,ignore
-// We are making use of this impl in the code above, since we call `From::from`
-// on a `&'static str`.
-impl<'a> From<&'a str> for Box<Error>
-
-// But this is also useful when you need to allocate a new string for an
-// error message, usually with `format!`.
-impl From<String> for Box<Error>
-```
-
-Since `search` now returns a `Result<T, E>`, `main` should use case analysis
-when calling `search`:
-
-```rust,ignore
-...
-    match search(data_path, city) {
-        Ok(pops) => {
-            for pop in pops {
-                println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
-            }
-        }
-        Err(err) => println!("{}", err)
-    }
-...
-```
-
-Now that we've seen how to do proper error handling with `Box<Error>`, let's
-try a different approach with our own custom error type. But first, let's take
-a quick break from error handling and add support for reading from `stdin`.
-
-## Reading from stdin
-
-In our program, we accept a single file for input and do one pass over the
-data. This means we probably should be able to accept input on stdin. But maybe
-we like the current format too—so let's have both!
-
-Adding support for stdin is actually quite easy. There are only three things we
-have to do:
-
-1. Tweak the program arguments so that a single parameter—the
-   city—can be accepted while the population data is read from stdin.
-2. Modify the program so that an option `-f` can take the file, if it
-    is not passed into stdin.
-3. Modify the `search` function to take an *optional* file path. When `None`,
-   it should know to read from stdin.
-
-First, here's the new usage:
-
-```rust,ignore
-fn print_usage(program: &str, opts: Options) {
-    println!("{}", opts.usage(&format!("Usage: {} [options] <city>", program)));
-}
-```
-Of course we need to adapt the argument handling code:
-
-```rust,ignore
-...
-    let mut opts = Options::new();
-    opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
-    opts.optflag("h", "help", "Show this usage message.");
-    ...
-    let data_path = matches.opt_str("f");
-
-    let city = if !matches.free.is_empty() {
-        &matches.free[0]
-    } else {
-        print_usage(&program, opts);
-        return;
-    };
-
-    match search(&data_path, city) {
-        Ok(pops) => {
-            for pop in pops {
-                println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
-            }
-        }
-        Err(err) => println!("{}", err)
-    }
-...
-```
-
-We've made the user experience a bit nicer by showing the usage message,
-instead of a panic from an out-of-bounds index, when `city`, the
-remaining free argument, is not present.
-
-Modifying `search` is slightly trickier. The `csv` crate can build a
-parser out of
-[any type that implements `io::Read`](http://burntsushi.net/rustdoc/csv/struct.Reader.html#method.from_reader).
-But how can we use the same code over both types? There's actually a
-couple ways we could go about this. One way is to write `search` such
-that it is generic on some type parameter `R` that satisfies
-`io::Read`. Another way is to use trait objects:
-
-```rust,ignore
-use std::io;
-
-// The rest of the code before this is unchanged.
-
-fn search<P: AsRef<Path>>
-         (file_path: &Option<P>, city: &str)
-         -> Result<Vec<PopulationCount>, Box<Error>> {
-    let mut found = vec![];
-    let input: Box<io::Read> = match *file_path {
-        None => Box::new(io::stdin()),
-        Some(ref file_path) => Box::new(try!(File::open(file_path))),
-    };
-    let mut rdr = csv::Reader::from_reader(input);
-    // The rest remains unchanged!
-}
-```
-
-## Error handling with a custom type
-
-Previously, we learned how to
-[compose errors using a custom error type](#composing-custom-error-types).
-We did this by defining our error type as an `enum` and implementing `Error`
-and `From`.
-
-Since we have three distinct errors (IO, CSV parsing and not found), let's
-define an `enum` with three variants:
-
-```rust,ignore
-#[derive(Debug)]
-enum CliError {
-    Io(io::Error),
-    Csv(csv::Error),
-    NotFound,
-}
-```
-
-And now for impls on `Display` and `Error`:
-
-```rust,ignore
-use std::fmt;
-
-impl fmt::Display for CliError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            CliError::Io(ref err) => err.fmt(f),
-            CliError::Csv(ref err) => err.fmt(f),
-            CliError::NotFound => write!(f, "No matching cities with a \
-                                             population were found."),
-        }
-    }
-}
-
-impl Error for CliError {
-    fn description(&self) -> &str {
-        match *self {
-            CliError::Io(ref err) => err.description(),
-            CliError::Csv(ref err) => err.description(),
-            CliError::NotFound => "not found",
-        }
-    }
-
-    fn cause(&self) -> Option<&Error> {
-        match *self {
-            CliError::Io(ref err) => Some(err),
-            CliError::Csv(ref err) => Some(err),
-            // Our custom error doesn't have an underlying cause,
-            // but we could modify it so that it does.
-            CliError::NotFound => None,
-        }
-    }
-}
-```
-
-Before we can use our `CliError` type in our `search` function, we need to
-provide a couple `From` impls. How do we know which impls to provide? Well,
-we'll need to convert from both `io::Error` and `csv::Error` to `CliError`.
-Those are the only external errors, so we'll only need two `From` impls for
-now:
-
-```rust,ignore
-impl From<io::Error> for CliError {
-    fn from(err: io::Error) -> CliError {
-        CliError::Io(err)
-    }
-}
-
-impl From<csv::Error> for CliError {
-    fn from(err: csv::Error) -> CliError {
-        CliError::Csv(err)
-    }
-}
-```
-
-The `From` impls are important because of how
-[`try!` is defined](#code-try-def). In particular, if an error occurs,
-`From::from` is called on the error, which in this case, will convert it to our
-own error type `CliError`.
-
-With the `From` impls done, we only need to make two small tweaks to our
-`search` function: the return type and the “not found” error. Here it is in
-full:
-
-```rust,ignore
-fn search<P: AsRef<Path>>
-         (file_path: &Option<P>, city: &str)
-         -> Result<Vec<PopulationCount>, CliError> {
-    let mut found = vec![];
-    let input: Box<io::Read> = match *file_path {
-        None => Box::new(io::stdin()),
-        Some(ref file_path) => Box::new(try!(File::open(file_path))),
-    };
-    let mut rdr = csv::Reader::from_reader(input);
-    for row in rdr.decode::<Row>() {
-        let row = try!(row);
-        match row.population {
-            None => { } // Skip it.
-            Some(count) => if row.city == city {
-                found.push(PopulationCount {
-                    city: row.city,
-                    country: row.country,
-                    count: count,
-                });
-            },
-        }
-    }
-    if found.is_empty() {
-        Err(CliError::NotFound)
-    } else {
-        Ok(found)
-    }
-}
-```
-
-No other changes are necessary.
-
-## Adding functionality
-
-Writing generic code is great, because generalizing stuff is cool, and
-it can then be useful later. But sometimes, the juice isn't worth the
-squeeze. Look at what we just did in the previous step:
-
-1. Defined a new error type.
-2. Added impls for `Error`, `Display` and two for `From`.
-
-The big downside here is that our program didn't improve a whole lot.
-There is quite a bit of overhead to representing errors with `enum`s,
-especially in short programs like this.
-
-*One* useful aspect of using a custom error type like we've done here is that
-the `main` function can now choose to handle errors differently. Previously,
-with `Box<Error>`, it didn't have much of a choice: just print the message.
-We're still doing that here, but what if we wanted to, say, add a `--quiet`
-flag? The `--quiet` flag should silence any verbose output.
-
-Right now, if the program doesn't find a match, it will output a message saying
-so. This can be a little clumsy, especially if you intend for the program to
-be used in shell scripts.
-
-So let's start by adding the flags. Like before, we need to tweak the usage
-string and add a flag to the Option variable. Once we've done that, Getopts does the rest:
-
-```rust,ignore
-...
-    let mut opts = Options::new();
-    opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
-    opts.optflag("h", "help", "Show this usage message.");
-    opts.optflag("q", "quiet", "Silences errors and warnings.");
-...
-```
-
-Now we only need to implement our “quiet” functionality. This requires us to
-tweak the case analysis in `main`:
-
-```rust,ignore
-use std::process;
-...
-    match search(&data_path, city) {
-        Err(CliError::NotFound) if matches.opt_present("q") => process::exit(1),
-        Err(err) => panic!("{}", err),
-        Ok(pops) => for pop in pops {
-            println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
-        }
-    }
-...
-```
-
-Certainly, we don't want to be quiet if there was an IO error or if the data
-failed to parse. Therefore, we use case analysis to check if the error type is
-`NotFound` *and* if `--quiet` has been enabled. If the search failed, we still
-quit with an exit code (following `grep`'s convention).
-
-If we had stuck with `Box<Error>`, then it would be pretty tricky to implement
-the `--quiet` functionality.
-
-This pretty much sums up our case study. From here, you should be ready to go
-out into the world and write your own programs and libraries with proper error
-handling.
-
-# The Short Story
-
-Since this section is long, it is useful to have a quick summary for error
-handling in Rust. These are some good “rules of thumb." They are emphatically
-*not* commandments. There are probably good reasons to break every one of these
-heuristics!
-
-* If you're writing short example code that would be overburdened by error
-  handling, it's probably fine to use `unwrap` (whether that's
-  [`Result::unwrap`](../std/result/enum.Result.html#method.unwrap),
-  [`Option::unwrap`](../std/option/enum.Option.html#method.unwrap)
-  or preferably
-  [`Option::expect`](../std/option/enum.Option.html#method.expect)).
-  Consumers of your code should know to use proper error handling. (If they
-  don't, send them here!)
-* If you're writing a quick 'n' dirty program, don't feel ashamed if you use
-  `unwrap`. Be warned: if it winds up in someone else's hands, don't be
-  surprised if they are agitated by poor error messages!
-* If you're writing a quick 'n' dirty program and feel ashamed about panicking
-  anyway, then use either a `String` or a `Box<Error>` for your
-  error type.
-* Otherwise, in a program, define your own error types with appropriate
-  [`From`](../std/convert/trait.From.html)
-  and
-  [`Error`](../std/error/trait.Error.html)
-  impls to make the [`try!`](../std/macro.try.html)
-  macro more ergonomic.
-* If you're writing a library and your code can produce errors, define your own
-  error type and implement the
-  [`std::error::Error`](../std/error/trait.Error.html)
-  trait. Where appropriate, implement
-  [`From`](../std/convert/trait.From.html) to make both
-  your library code and the caller's code easier to write. (Because of Rust's
-  coherence rules, callers will not be able to impl `From` on your error type,
-  so your library should do it.)
-* Learn the combinators defined on
-  [`Option`](../std/option/enum.Option.html)
-  and
-  [`Result`](../std/result/enum.Result.html).
-  Using them exclusively can be a bit tiring at times, but I've personally
-  found a healthy mix of `try!` and combinators to be quite appealing.
-  `and_then`, `map` and `unwrap_or` are my favorites.
-
-[1]: ../book/patterns.html
-[2]: ../std/option/enum.Option.html#method.map
-[3]: ../std/option/enum.Option.html#method.unwrap_or
-[4]: ../std/option/enum.Option.html#method.unwrap_or_else
-[5]: ../std/option/enum.Option.html
-[6]: ../std/result/index.html
-[7]: ../std/result/enum.Result.html#method.unwrap
-[8]: ../std/fmt/trait.Debug.html
-[9]: ../std/primitive.str.html#method.parse
-[10]: ../book/associated-types.html
-[11]: https://github.com/petewarden/dstkdata
-[12]: http://burntsushi.net/stuff/worldcitiespop.csv.gz
-[13]: http://burntsushi.net/stuff/uscitiespop.csv.gz
-[14]: http://doc.crates.io/guide.html
-[15]: http://doc.rust-lang.org/getopts/getopts/index.html
diff --git a/src/doc/book/src/ffi.md b/src/doc/book/src/ffi.md
deleted file mode 100644 (file)
index 3dd9aa3..0000000
+++ /dev/null
@@ -1,767 +0,0 @@
-# Foreign Function Interface
-
-# Introduction
-
-This guide will use the [snappy](https://github.com/google/snappy)
-compression/decompression library as an introduction to writing bindings for
-foreign code. Rust is currently unable to call directly into a C++ library, but
-snappy includes a C interface (documented in
-[`snappy-c.h`](https://github.com/google/snappy/blob/master/snappy-c.h)).
-
-## A note about libc
-
-Many of these examples use [the `libc` crate][libc], which provides various
-type definitions for C types, among other things. If you’re trying these
-examples yourself, you’ll need to add `libc` to your `Cargo.toml`:
-
-```toml
-[dependencies]
-libc = "0.2.0"
-```
-
-[libc]: https://crates.io/crates/libc
-
-and add `extern crate libc;` to your crate root.
-
-## Calling foreign functions
-
-The following is a minimal example of calling a foreign function which will
-compile if snappy is installed:
-
-```rust,no_run
-# #![feature(libc)]
-extern crate libc;
-use libc::size_t;
-
-#[link(name = "snappy")]
-extern {
-    fn snappy_max_compressed_length(source_length: size_t) -> size_t;
-}
-
-fn main() {
-    let x = unsafe { snappy_max_compressed_length(100) };
-    println!("max compressed length of a 100 byte buffer: {}", x);
-}
-```
-
-The `extern` block is a list of function signatures in a foreign library, in
-this case with the platform's C ABI. The `#[link(...)]` attribute is used to
-instruct the linker to link against the snappy library so the symbols are
-resolved.
-
-Foreign functions are assumed to be unsafe so calls to them need to be wrapped
-with `unsafe {}` as a promise to the compiler that everything contained within
-truly is safe. C libraries often expose interfaces that aren't thread-safe, and
-almost any function that takes a pointer argument isn't valid for all possible
-inputs since the pointer could be dangling, and raw pointers fall outside of
-Rust's safe memory model.
-
-When declaring the argument types to a foreign function, the Rust compiler
-cannot check if the declaration is correct, so specifying it correctly is part
-of keeping the binding correct at runtime.
-
-The `extern` block can be extended to cover the entire snappy API:
-
-```rust,no_run
-# #![feature(libc)]
-extern crate libc;
-use libc::{c_int, size_t};
-
-#[link(name = "snappy")]
-extern {
-    fn snappy_compress(input: *const u8,
-                       input_length: size_t,
-                       compressed: *mut u8,
-                       compressed_length: *mut size_t) -> c_int;
-    fn snappy_uncompress(compressed: *const u8,
-                         compressed_length: size_t,
-                         uncompressed: *mut u8,
-                         uncompressed_length: *mut size_t) -> c_int;
-    fn snappy_max_compressed_length(source_length: size_t) -> size_t;
-    fn snappy_uncompressed_length(compressed: *const u8,
-                                  compressed_length: size_t,
-                                  result: *mut size_t) -> c_int;
-    fn snappy_validate_compressed_buffer(compressed: *const u8,
-                                         compressed_length: size_t) -> c_int;
-}
-# fn main() {}
-```
-
-# Creating a safe interface
-
-The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts
-like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe
-internal details.
-
-Wrapping the functions which expect buffers involves using the `slice::raw` module to manipulate Rust
-vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous block of memory. The
-length is the number of elements currently contained, and the capacity is the total size in elements of
-the allocated memory. The length is less than or equal to the capacity.
-
-```rust
-# #![feature(libc)]
-# extern crate libc;
-# use libc::{c_int, size_t};
-# unsafe fn snappy_validate_compressed_buffer(_: *const u8, _: size_t) -> c_int { 0 }
-# fn main() {}
-pub fn validate_compressed_buffer(src: &[u8]) -> bool {
-    unsafe {
-        snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0
-    }
-}
-```
-
-The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the
-guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function
-signature.
-
-The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be
-allocated to hold the output too.
-
-The `snappy_max_compressed_length` function can be used to allocate a vector with the maximum
-required capacity to hold the compressed output. The vector can then be passed to the
-`snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
-the true length after compression for setting the length.
-
-```rust
-# #![feature(libc)]
-# extern crate libc;
-# use libc::{size_t, c_int};
-# unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8,
-#                           d: *mut size_t) -> c_int { 0 }
-# unsafe fn snappy_max_compressed_length(a: size_t) -> size_t { a }
-# fn main() {}
-pub fn compress(src: &[u8]) -> Vec<u8> {
-    unsafe {
-        let srclen = src.len() as size_t;
-        let psrc = src.as_ptr();
-
-        let mut dstlen = snappy_max_compressed_length(srclen);
-        let mut dst = Vec::with_capacity(dstlen as usize);
-        let pdst = dst.as_mut_ptr();
-
-        snappy_compress(psrc, srclen, pdst, &mut dstlen);
-        dst.set_len(dstlen as usize);
-        dst
-    }
-}
-```
-
-Decompression is similar, because snappy stores the uncompressed size as part of the compression
-format and `snappy_uncompressed_length` will retrieve the exact buffer size required.
-
-```rust
-# #![feature(libc)]
-# extern crate libc;
-# use libc::{size_t, c_int};
-# unsafe fn snappy_uncompress(compressed: *const u8,
-#                             compressed_length: size_t,
-#                             uncompressed: *mut u8,
-#                             uncompressed_length: *mut size_t) -> c_int { 0 }
-# unsafe fn snappy_uncompressed_length(compressed: *const u8,
-#                                      compressed_length: size_t,
-#                                      result: *mut size_t) -> c_int { 0 }
-# fn main() {}
-pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> {
-    unsafe {
-        let srclen = src.len() as size_t;
-        let psrc = src.as_ptr();
-
-        let mut dstlen: size_t = 0;
-        snappy_uncompressed_length(psrc, srclen, &mut dstlen);
-
-        let mut dst = Vec::with_capacity(dstlen as usize);
-        let pdst = dst.as_mut_ptr();
-
-        if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {
-            dst.set_len(dstlen as usize);
-            Some(dst)
-        } else {
-            None // SNAPPY_INVALID_INPUT
-        }
-    }
-}
-```
-
-Then, we can add some tests to show how to use them.
-
-```rust
-# #![feature(libc)]
-# extern crate libc;
-# use libc::{c_int, size_t};
-# unsafe fn snappy_compress(input: *const u8,
-#                           input_length: size_t,
-#                           compressed: *mut u8,
-#                           compressed_length: *mut size_t)
-#                           -> c_int { 0 }
-# unsafe fn snappy_uncompress(compressed: *const u8,
-#                             compressed_length: size_t,
-#                             uncompressed: *mut u8,
-#                             uncompressed_length: *mut size_t)
-#                             -> c_int { 0 }
-# unsafe fn snappy_max_compressed_length(source_length: size_t) -> size_t { 0 }
-# unsafe fn snappy_uncompressed_length(compressed: *const u8,
-#                                      compressed_length: size_t,
-#                                      result: *mut size_t)
-#                                      -> c_int { 0 }
-# unsafe fn snappy_validate_compressed_buffer(compressed: *const u8,
-#                                             compressed_length: size_t)
-#                                             -> c_int { 0 }
-# fn main() { }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn valid() {
-        let d = vec![0xde, 0xad, 0xd0, 0x0d];
-        let c: &[u8] = &compress(&d);
-        assert!(validate_compressed_buffer(c));
-        assert!(uncompress(c) == Some(d));
-    }
-
-    #[test]
-    fn invalid() {
-        let d = vec![0, 0, 0, 0];
-        assert!(!validate_compressed_buffer(&d));
-        assert!(uncompress(&d).is_none());
-    }
-
-    #[test]
-    fn empty() {
-        let d = vec![];
-        assert!(!validate_compressed_buffer(&d));
-        assert!(uncompress(&d).is_none());
-        let c = compress(&d);
-        assert!(validate_compressed_buffer(&c));
-        assert!(uncompress(&c) == Some(d));
-    }
-}
-```
-
-# Destructors
-
-Foreign libraries often hand off ownership of resources to the calling code.
-When this occurs, we must use Rust's destructors to provide safety and guarantee
-the release of these resources (especially in the case of panic).
-
-For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html).
-
-# Callbacks from C code to Rust functions
-
-Some external libraries require the usage of callbacks to report back their
-current state or intermediate data to the caller.
-It is possible to pass functions defined in Rust to an external library.
-The requirement for this is that the callback function is marked as `extern`
-with the correct calling convention to make it callable from C code.
-
-The callback function can then be sent through a registration call
-to the C library and afterwards be invoked from there.
-
-A basic example is:
-
-Rust code:
-
-```rust,no_run
-extern fn callback(a: i32) {
-    println!("I'm called from C with value {0}", a);
-}
-
-#[link(name = "extlib")]
-extern {
-   fn register_callback(cb: extern fn(i32)) -> i32;
-   fn trigger_callback();
-}
-
-fn main() {
-    unsafe {
-        register_callback(callback);
-        trigger_callback(); // Triggers the callback.
-    }
-}
-```
-
-C code:
-
-```c
-typedef void (*rust_callback)(int32_t);
-rust_callback cb;
-
-int32_t register_callback(rust_callback callback) {
-    cb = callback;
-    return 1;
-}
-
-void trigger_callback() {
-  cb(7); // Will call callback(7) in Rust.
-}
-```
-
-In this example Rust's `main()` will call `trigger_callback()` in C,
-which would, in turn, call back to `callback()` in Rust.
-
-
-## Targeting callbacks to Rust objects
-
-The former example showed how a global function can be called from C code.
-However it is often desired that the callback is targeted to a special
-Rust object. This could be the object that represents the wrapper for the
-respective C object.
-
-This can be achieved by passing a raw pointer to the object down to the
-C library. The C library can then include the pointer to the Rust object in
-the notification. This will allow the callback to unsafely access the
-referenced Rust object.
-
-Rust code:
-
-```rust,no_run
-#[repr(C)]
-struct RustObject {
-    a: i32,
-    // Other members...
-}
-
-extern "C" fn callback(target: *mut RustObject, a: i32) {
-    println!("I'm called from C with value {0}", a);
-    unsafe {
-        // Update the value in RustObject with the value received from the callback:
-        (*target).a = a;
-    }
-}
-
-#[link(name = "extlib")]
-extern {
-   fn register_callback(target: *mut RustObject,
-                        cb: extern fn(*mut RustObject, i32)) -> i32;
-   fn trigger_callback();
-}
-
-fn main() {
-    // Create the object that will be referenced in the callback:
-    let mut rust_object = Box::new(RustObject { a: 5 });
-
-    unsafe {
-        register_callback(&mut *rust_object, callback);
-        trigger_callback();
-    }
-}
-```
-
-C code:
-
-```c
-typedef void (*rust_callback)(void*, int32_t);
-void* cb_target;
-rust_callback cb;
-
-int32_t register_callback(void* callback_target, rust_callback callback) {
-    cb_target = callback_target;
-    cb = callback;
-    return 1;
-}
-
-void trigger_callback() {
-  cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust.
-}
-```
-
-## Asynchronous callbacks
-
-In the previously given examples the callbacks are invoked as a direct reaction
-to a function call to the external C library.
-The control over the current thread is switched from Rust to C to Rust for the
-execution of the callback, but in the end the callback is executed on the
-same thread that called the function which triggered the callback.
-
-Things get more complicated when the external library spawns its own threads
-and invokes callbacks from there.
-In these cases access to Rust data structures inside the callbacks is
-especially unsafe and proper synchronization mechanisms must be used.
-Besides classical synchronization mechanisms like mutexes, one possibility in
-Rust is to use channels (in `std::sync::mpsc`) to forward data from the C
-thread that invoked the callback into a Rust thread.
-
-If an asynchronous callback targets a special object in the Rust address space
-it is also absolutely necessary that no more callbacks are performed by the
-C library after the respective Rust object gets destroyed.
-This can be achieved by unregistering the callback in the object's
-destructor and designing the library in a way that guarantees that no
-callback will be performed after deregistration.
-
-# Linking
-
-The `link` attribute on `extern` blocks provides the basic building block for
-instructing rustc how it will link to native libraries. There are two accepted
-forms of the link attribute today:
-
-* `#[link(name = "foo")]`
-* `#[link(name = "foo", kind = "bar")]`
-
-In both of these cases, `foo` is the name of the native library that we're
-linking to, and in the second case `bar` is the type of native library that the
-compiler is linking to. There are currently three known types of native
-libraries:
-
-* Dynamic - `#[link(name = "readline")]`
-* Static - `#[link(name = "my_build_dependency", kind = "static")]`
-* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]`
-
-Note that frameworks are only available on macOS targets.
-
-The different `kind` values are meant to differentiate how the native library
-participates in linkage. From a linkage perspective, the Rust compiler creates
-two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary).
-Native dynamic library and framework dependencies are propagated to the final
-artifact boundary, while static library dependencies are not propagated at
-all, because the static libraries are integrated directly into the subsequent
-artifact.
-
-A few examples of how this model can be used are:
-
-* A native build dependency. Sometimes some C/C++ glue is needed when writing
-  some Rust code, but distribution of the C/C++ code in a library format is
-  a burden. In this case, the code will be archived into `libfoo.a` and then the
-  Rust crate would declare a dependency via `#[link(name = "foo", kind =
-  "static")]`.
-
-  Regardless of the flavor of output for the crate, the native static library
-  will be included in the output, meaning that distribution of the native static
-  library is not necessary.
-
-* A normal dynamic dependency. Common system libraries (like `readline`) are
-  available on a large number of systems, and often a static copy of these
-  libraries cannot be found. When this dependency is included in a Rust crate,
-  partial targets (like rlibs) will not link to the library, but when the rlib
-  is included in a final target (like a binary), the native library will be
-  linked in.
-
-On macOS, frameworks behave with the same semantics as a dynamic library.
-
-# Unsafe blocks
-
-Some operations, like dereferencing raw pointers or calling functions that have been marked
-unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to
-the compiler that the unsafety does not leak out of the block.
-
-Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like
-this:
-
-```rust
-unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr }
-```
-
-This function can only be called from an `unsafe` block or another `unsafe` function.
-
-# Accessing foreign globals
-
-Foreign APIs often export a global variable which could do something like track
-global state. In order to access these variables, you declare them in `extern`
-blocks with the `static` keyword:
-
-```rust,no_run
-# #![feature(libc)]
-extern crate libc;
-
-#[link(name = "readline")]
-extern {
-    static rl_readline_version: libc::c_int;
-}
-
-fn main() {
-    println!("You have readline version {} installed.",
-             unsafe { rl_readline_version as i32 });
-}
-```
-
-Alternatively, you may need to alter global state provided by a foreign
-interface. To do this, statics can be declared with `mut` so we can mutate
-them.
-
-```rust,no_run
-# #![feature(libc)]
-extern crate libc;
-
-use std::ffi::CString;
-use std::ptr;
-
-#[link(name = "readline")]
-extern {
-    static mut rl_prompt: *const libc::c_char;
-}
-
-fn main() {
-    let prompt = CString::new("[my-awesome-shell] $").unwrap();
-    unsafe {
-        rl_prompt = prompt.as_ptr();
-
-        println!("{:?}", rl_prompt);
-
-        rl_prompt = ptr::null();
-    }
-}
-```
-
-Note that all interaction with a `static mut` is unsafe, both reading and
-writing. Dealing with global mutable state requires a great deal of care.
-
-# Foreign calling conventions
-
-Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when
-calling foreign functions. Some foreign functions, most notably the Windows API, use other calling
-conventions. Rust provides a way to tell the compiler which convention to use:
-
-```rust
-# #![feature(libc)]
-extern crate libc;
-
-#[cfg(all(target_os = "win32", target_arch = "x86"))]
-#[link(name = "kernel32")]
-#[allow(non_snake_case)]
-extern "stdcall" {
-    fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int;
-}
-# fn main() { }
-```
-
-This applies to the entire `extern` block. The list of supported ABI constraints
-are:
-
-* `stdcall`
-* `aapcs`
-* `cdecl`
-* `fastcall`
-* `vectorcall`
-This is currently hidden behind the `abi_vectorcall` gate and is subject to change.
-* `Rust`
-* `rust-intrinsic`
-* `system`
-* `C`
-* `win64`
-* `sysv64`
-
-Most of the abis in this list are self-explanatory, but the `system` abi may
-seem a little odd. This constraint selects whatever the appropriate ABI is for
-interoperating with the target's libraries. For example, on win32 with a x86
-architecture, this means that the abi used would be `stdcall`. On x86_64,
-however, windows uses the `C` calling convention, so `C` would be used. This
-means that in our previous example, we could have used `extern "system" { ... }`
-to define a block for all windows systems, not only x86 ones.
-
-# Interoperability with foreign code
-
-Rust guarantees that the layout of a `struct` is compatible with the platform's
-representation in C only if the `#[repr(C)]` attribute is applied to it.
-`#[repr(C, packed)]` can be used to lay out struct members without padding.
-`#[repr(C)]` can also be applied to an enum.
-
-Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point
-to the contained object. However, they should not be manually created because
-they are managed by internal allocators. References can safely be assumed to be
-non-nullable pointers directly to the type.  However, breaking the borrow
-checking or mutability rules is not guaranteed to be safe, so prefer using raw
-pointers (`*`) if that's needed because the compiler can't make as many
-assumptions about them.
-
-Vectors and strings share the same basic memory layout, and utilities are
-available in the `vec` and `str` modules for working with C APIs. However,
-strings are not terminated with `\0`. If you need a NUL-terminated string for
-interoperability with C, you should use the `CString` type in the `std::ffi`
-module.
-
-The [`libc` crate on crates.io][libc] includes type aliases and function
-definitions for the C standard library in the `libc` module, and Rust links
-against `libc` and `libm` by default.
-
-# Variadic functions
-
-In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can
-be achieved in Rust by specifying `...` within the argument list of a foreign function declaration:
-
-```no_run
-extern {
-    fn foo(x: i32, ...);
-}
-
-fn main() {
-    unsafe {
-        foo(10, 20, 30, 40, 50);
-    }
-}
-```
-
-Normal Rust functions can *not* be variadic:
-
-```ignore
-// This will not compile
-
-fn foo(x: i32, ...) { }
-```
-
-# The "nullable pointer optimization"
-
-Certain Rust types are defined to never be `null`. This includes references (`&T`,
-`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). When
-interfacing with C, pointers that might be `null` are often used, which would seem to
-require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types.
-However, the language provides a workaround.
-
-As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains
-exactly two variants, one of which contains no data and the other contains a field of one of the
-non-nullable types listed above.  This means no extra space is required for a discriminant; rather,
-the empty variant is represented by putting a `null` value into the non-nullable field. This is
-called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible
-types.
-
-The most common type that takes advantage of the nullable pointer optimization is `Option<T>`,
-where `None` corresponds to `null`. So `Option<extern "C" fn(c_int) -> c_int>` is a correct way
-to represent a nullable function pointer using the C ABI (corresponding to the C type
-`int (*)(int)`).
-
-Here is a contrived example. Let's say some C library has a facility for registering a
-callback, which gets called in certain situations. The callback is passed a function pointer
-and an integer and it is supposed to run the function with the integer as a parameter. So
-we have function pointers flying across the FFI boundary in both directions.
-
-```rust
-# #![feature(libc)]
-extern crate libc;
-use libc::c_int;
-
-# #[cfg(hidden)]
-extern "C" {
-    /// Registers the callback.
-    fn register(cb: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>, c_int) -> c_int>);
-}
-# unsafe fn register(_: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>,
-#                                            c_int) -> c_int>)
-# {}
-
-/// This fairly useless function receives a function pointer and an integer
-/// from C, and returns the result of calling the function with the integer.
-/// In case no function is provided, it squares the integer by default.
-extern "C" fn apply(process: Option<extern "C" fn(c_int) -> c_int>, int: c_int) -> c_int {
-    match process {
-        Some(f) => f(int),
-        None    => int * int
-    }
-}
-
-fn main() {
-    unsafe {
-        register(Some(apply));
-    }
-}
-```
-
-And the code on the C side looks like this:
-
-```c
-void register(void (*f)(void (*)(int), int)) {
-    ...
-}
-```
-
-No `transmute` required!
-
-# Calling Rust code from C
-
-You may wish to compile Rust code in a way so that it can be called from C. This is
-fairly easy, but requires a few things:
-
-```rust
-#[no_mangle]
-pub extern fn hello_rust() -> *const u8 {
-    "Hello, world!\0".as_ptr()
-}
-# fn main() {}
-```
-
-The `extern` makes this function adhere to the C calling convention, as
-discussed above in "[Foreign Calling
-Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle`
-attribute turns off Rust's name mangling, so that it is easier to link to.
-
-# FFI and panics
-
-It’s important to be mindful of `panic!`s when working with FFI. A `panic!`
-across an FFI boundary is undefined behavior. If you’re writing code that may
-panic, you should run it in a closure with [`catch_unwind`]:
-
-```rust
-use std::panic::catch_unwind;
-
-#[no_mangle]
-pub extern fn oh_no() -> i32 {
-    let result = catch_unwind(|| {
-        panic!("Oops!");
-    });
-    match result {
-        Ok(_) => 0,
-        Err(_) => 1,
-    }
-}
-
-fn main() {}
-```
-
-Please note that [`catch_unwind`] will only catch unwinding panics, not
-those who abort the process. See the documentation of [`catch_unwind`]
-for more information.
-
-[`catch_unwind`]: ../std/panic/fn.catch_unwind.html
-
-# Representing opaque structs
-
-Sometimes, a C library wants to provide a pointer to something, but not let you
-know the internal details of the thing it wants. The simplest way is to use a
-`void *` argument:
-
-```c
-void foo(void *arg);
-void bar(void *arg);
-```
-
-We can represent this in Rust with the `c_void` type:
-
-```rust
-# #![feature(libc)]
-extern crate libc;
-
-extern "C" {
-    pub fn foo(arg: *mut libc::c_void);
-    pub fn bar(arg: *mut libc::c_void);
-}
-# fn main() {}
-```
-
-This is a perfectly valid way of handling the situation. However, we can do a bit
-better. To solve this, some C libraries will instead create a `struct`, where
-the details and memory layout of the struct are private. This gives some amount
-of type safety. These structures are called ‘opaque’. Here’s an example, in C:
-
-```c
-struct Foo; /* Foo is a structure, but its contents are not part of the public interface */
-struct Bar;
-void foo(struct Foo *arg);
-void bar(struct Bar *arg);
-```
-
-To do this in Rust, let’s create our own opaque types with `enum`:
-
-```rust
-pub enum Foo {}
-pub enum Bar {}
-
-extern "C" {
-    pub fn foo(arg: *mut Foo);
-    pub fn bar(arg: *mut Bar);
-}
-# fn main() {}
-```
-
-By using an `enum` with no variants, we create an opaque type that we can’t
-instantiate, as it has no variants. But because our `Foo` and `Bar` types are
-different, we’ll get type safety between the two of them, so we cannot
-accidentally pass a pointer to `Foo` to `bar()`.
diff --git a/src/doc/book/src/functions.md b/src/doc/book/src/functions.md
deleted file mode 100644 (file)
index 96c8e9f..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-# Functions
-
-Every Rust program has at least one function, the `main` function:
-
-```rust
-fn main() {
-}
-```
-
-This is the simplest possible function declaration. As we mentioned before,
-`fn` says ‘this is a function’, followed by the name, some parentheses because
-this function takes no arguments, and then some curly braces to indicate the
-body. Here’s a function named `foo`:
-
-```rust
-fn foo() {
-}
-```
-
-So, what about taking arguments? Here’s a function that prints a number:
-
-```rust
-fn print_number(x: i32) {
-    println!("x is: {}", x);
-}
-```
-
-Here’s a complete program that uses `print_number`:
-
-```rust
-fn main() {
-    print_number(5);
-}
-
-fn print_number(x: i32) {
-    println!("x is: {}", x);
-}
-```
-
-As you can see, function arguments work very similar to `let` declarations:
-you add a type to the argument name, after a colon.
-
-Here’s a complete program that adds two numbers together and prints them:
-
-```rust
-fn main() {
-    print_sum(5, 6);
-}
-
-fn print_sum(x: i32, y: i32) {
-    println!("sum is: {}", x + y);
-}
-```
-
-You separate arguments with a comma, both when you call the function, as well
-as when you declare it.
-
-Unlike `let`, you _must_ declare the types of function arguments. This does
-not work:
-
-```rust,ignore
-fn print_sum(x, y) {
-    println!("sum is: {}", x + y);
-}
-```
-
-You get this error:
-
-```text
-expected one of `!`, `:`, or `@`, found `)`
-fn print_sum(x, y) {
-```
-
-This is a deliberate design decision. While full-program inference is possible,
-languages which have it, like Haskell, often suggest that documenting your
-types explicitly is a best-practice. We agree that forcing functions to declare
-types while allowing for inference inside of function bodies is a wonderful
-sweet spot between full inference and no inference.
-
-What about returning a value? Here’s a function that adds one to an integer:
-
-```rust
-fn add_one(x: i32) -> i32 {
-    x + 1
-}
-```
-
-Rust functions return exactly one value, and you declare the type after an
-‘arrow’, which is a dash (`-`) followed by a greater-than sign (`>`). The last
-line of a function determines what it returns. You’ll note the lack of a
-semicolon here. If we added it in:
-
-```rust,ignore
-fn add_one(x: i32) -> i32 {
-    x + 1;
-}
-```
-
-We would get an error:
-
-```text
-error: not all control paths return a value
-fn add_one(x: i32) -> i32 {
-     x + 1;
-}
-
-help: consider removing this semicolon:
-     x + 1;
-          ^
-```
-
-This reveals two interesting things about Rust: it is an expression-based
-language, and semicolons are different from semicolons in other ‘curly brace
-and semicolon’-based languages. These two things are related.
-
-## Expressions vs. Statements
-
-Rust is primarily an expression-based language. There are only two kinds of
-statements, and everything else is an expression.
-
-So what's the difference? Expressions return a value, and statements do not.
-That’s why we end up with ‘not all control paths return a value’ here: the
-statement `x + 1;` doesn’t return a value. There are two kinds of statements in
-Rust: ‘declaration statements’ and ‘expression statements’. Everything else is
-an expression. Let’s talk about declaration statements first.
-
-In some languages, variable bindings can be written as expressions, not
-statements. Like Ruby:
-
-```ruby
-x = y = 5
-```
-
-In Rust, however, using `let` to introduce a binding is _not_ an expression. The
-following will produce a compile-time error:
-
-```rust,ignore
-let x = (let y = 5); // Expected identifier, found keyword `let`.
-```
-
-The compiler is telling us here that it was expecting to see the beginning of
-an expression, and a `let` can only begin a statement, not an expression.
-
-Note that assigning to an already-bound variable (e.g. `y = 5`) is still an
-expression, although its value is not particularly useful. Unlike other
-languages where an assignment evaluates to the assigned value (e.g. `5` in the
-previous example), in Rust the value of an assignment is an empty tuple `()`
-because the assigned value can have [only one owner](ownership.html), and any
-other returned value would be too surprising:
-
-```rust
-let mut y = 5;
-
-let x = (y = 6);  // `x` has the value `()`, not `6`.
-```
-
-The second kind of statement in Rust is the *expression statement*. Its
-purpose is to turn any expression into a statement. In practical terms, Rust's
-grammar expects statements to follow other statements. This means that you use
-semicolons to separate expressions from each other. This means that Rust
-looks a lot like most other languages that require you to use semicolons
-at the end of every line, and you will see semicolons at the end of almost
-every line of Rust code you see.
-
-What is this exception that makes us say "almost"? You saw it already, in this
-code:
-
-```rust
-fn add_one(x: i32) -> i32 {
-    x + 1
-}
-```
-
-Our function claims to return an `i32`, but with a semicolon, it would return
-`()` instead. Rust realizes this probably isn’t what we want, and suggests
-removing the semicolon in the error we saw before.
-
-## Early returns
-
-But what about early returns? Rust does have a keyword for that, `return`:
-
-```rust
-fn foo(x: i32) -> i32 {
-    return x;
-
-    // We never run this code!
-    x + 1
-}
-```
-
-Using a `return` as the last line of a function works, but is considered poor
-style:
-
-```rust
-fn foo(x: i32) -> i32 {
-    return x + 1;
-}
-```
-
-The previous definition without `return` may look a bit strange if you haven’t
-worked in an expression-based language before, but it becomes intuitive over
-time.
-
-## Diverging functions
-
-Rust has some special syntax for ‘diverging functions’, which are functions that
-do not return:
-
-```rust
-fn diverges() -> ! {
-    panic!("This function never returns!");
-}
-```
-
-`panic!` is a macro, similar to `println!()` that we’ve already seen. Unlike
-`println!()`, `panic!()` causes the current thread of execution to crash with
-the given message. Because this function will cause a crash, it will never
-return, and so it has the type ‘`!`’, which is read ‘diverges’.
-
-If you add a main function that calls `diverges()` and run it, you’ll get
-some output that looks like this:
-
-```text
-thread ‘main’ panicked at ‘This function never returns!’, hello.rs:2
-```
-
-If you want more information, you can get a backtrace by setting the
-`RUST_BACKTRACE` environment variable:
-
-```text
-$ RUST_BACKTRACE=1 ./diverges
-thread 'main' panicked at 'This function never returns!', hello.rs:2
-Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
-stack backtrace:
-  hello::diverges
-        at ./hello.rs:2
-  hello::main
-        at ./hello.rs:6
-```
-
-If you want the complete backtrace and filenames:
-
-```text
-$ RUST_BACKTRACE=full ./diverges
-thread 'main' panicked at 'This function never returns!', hello.rs:2
-stack backtrace:
-   1:     0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r
-   2:     0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w
-   3:     0x7f402773960e - rt::unwind::begin_unwind_inner::h2844b8c5e81e79558Bw
-   4:     0x7f4027738893 - rt::unwind::begin_unwind::h4375279447423903650
-   5:     0x7f4027738809 - diverges::h2266b4c4b850236beaa
-   6:     0x7f40277389e5 - main::h19bb1149c2f00ecfBaa
-   7:     0x7f402773f514 - rt::unwind::try::try_fn::h13186883479104382231
-   8:     0x7f402773d1d8 - __rust_try
-   9:     0x7f402773f201 - rt::lang_start::ha172a3ce74bb453aK5w
-  10:     0x7f4027738a19 - main
-  11:     0x7f402694ab44 - __libc_start_main
-  12:     0x7f40277386c8 - <unknown>
-  13:                0x0 - <unknown>
-```
-
-If you need to override an already set `RUST_BACKTRACE`, 
-in cases when you cannot just unset the variable, 
-then set it to `0` to avoid getting a backtrace. 
-Any other value (even no value at all) turns on backtrace.
-
-```text
-$ export RUST_BACKTRACE=1
-...
-$ RUST_BACKTRACE=0 ./diverges 
-thread 'main' panicked at 'This function never returns!', hello.rs:2
-note: Run with `RUST_BACKTRACE=1` for a backtrace.
-```
-
-`RUST_BACKTRACE` also works with Cargo’s `run` command:
-
-```text
-$ RUST_BACKTRACE=full cargo run
-     Running `target/debug/diverges`
-thread 'main' panicked at 'This function never returns!', hello.rs:2
-stack backtrace:
-   1:     0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r
-   2:     0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w
-   3:     0x7f402773960e - rt::unwind::begin_unwind_inner::h2844b8c5e81e79558Bw
-   4:     0x7f4027738893 - rt::unwind::begin_unwind::h4375279447423903650
-   5:     0x7f4027738809 - diverges::h2266b4c4b850236beaa
-   6:     0x7f40277389e5 - main::h19bb1149c2f00ecfBaa
-   7:     0x7f402773f514 - rt::unwind::try::try_fn::h13186883479104382231
-   8:     0x7f402773d1d8 - __rust_try
-   9:     0x7f402773f201 - rt::lang_start::ha172a3ce74bb453aK5w
-  10:     0x7f4027738a19 - main
-  11:     0x7f402694ab44 - __libc_start_main
-  12:     0x7f40277386c8 - <unknown>
-  13:                0x0 - <unknown>
-```
-
-A diverging function can be used as any type:
-
-```rust,should_panic
-# fn diverges() -> ! {
-#    panic!("This function never returns!");
-# }
-let x: i32 = diverges();
-let x: String = diverges();
-```
-
-## Function pointers
-
-We can also create variable bindings which point to functions:
-
-```rust
-let f: fn(i32) -> i32;
-```
-
-`f` is a variable binding which points to a function that takes an `i32` as
-an argument and returns an `i32`. For example:
-
-```rust
-fn plus_one(i: i32) -> i32 {
-    i + 1
-}
-
-// Without type inference:
-let f: fn(i32) -> i32 = plus_one;
-
-// With type inference:
-let f = plus_one;
-```
-
-We can then use `f` to call the function:
-
-```rust
-# fn plus_one(i: i32) -> i32 { i + 1 }
-# let f = plus_one;
-let six = f(5);
-```
diff --git a/src/doc/book/src/generics.md b/src/doc/book/src/generics.md
deleted file mode 100644 (file)
index d02cd77..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-# Generics
-
-Sometimes, when writing a function or data type, we may want it to work for
-multiple types of arguments. In Rust, we can do this with generics.
-Generics are called ‘parametric polymorphism’ in type theory,
-which means that they are types or functions that have multiple forms (‘poly’
-is multiple, ‘morph’ is form) over a given parameter (‘parametric’).
-
-Anyway, enough type theory, let’s check out some generic code. Rust’s
-standard library provides a type, `Option<T>`, that’s generic:
-
-```rust
-enum Option<T> {
-    Some(T),
-    None,
-}
-```
-
-The `<T>` part, which you’ve seen a few times before, indicates that this is
-a generic data type. Inside the declaration of our `enum`, wherever we see a `T`,
-we substitute that type for the same type used in the generic. Here’s an
-example of using `Option<T>`, with some extra type annotations:
-
-```rust
-let x: Option<i32> = Some(5);
-```
-
-In the type declaration, we say `Option<i32>`. Note how similar this looks to
-`Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On
-the right-hand side of the binding, we make a `Some(T)`, where `T` is `5`.
-Since that’s an `i32`, the two sides match, and Rust is happy. If they didn’t
-match, we’d get an error:
-
-```rust,ignore
-let x: Option<f64> = Some(5);
-// error: mismatched types: expected `core::option::Option<f64>`,
-// found `core::option::Option<_>` (expected f64 but found integral variable)
-```
-
-That doesn’t mean we can’t make `Option<T>`s that hold an `f64`! They have
-to match up:
-
-```rust
-let x: Option<i32> = Some(5);
-let y: Option<f64> = Some(5.0f64);
-```
-
-This is just fine. One definition, multiple uses.
-
-Generics don’t have to only be generic over one type. Consider another type from Rust’s standard library that’s similar, `Result<T, E>`:
-
-```rust
-enum Result<T, E> {
-    Ok(T),
-    Err(E),
-}
-```
-
-This type is generic over _two_ types: `T` and `E`. By the way, the capital letters
-can be any letter you’d like. We could define `Result<T, E>` as:
-
-```rust
-enum Result<A, Z> {
-    Ok(A),
-    Err(Z),
-}
-```
-
-if we wanted to. Convention says that the first generic parameter should be
-`T`, for ‘type’, and that we use `E` for ‘error’. Rust doesn’t care, however.
-
-The `Result<T, E>` type is intended to be used to return the result of a
-computation, and to have the ability to return an error if it didn’t work out.
-
-## Generic functions
-
-We can write functions that take generic types with a similar syntax:
-
-```rust
-fn takes_anything<T>(x: T) {
-    // Do something with `x`.
-}
-```
-
-The syntax has two parts: the `<T>` says “this function is generic over one
-type, `T`”, and the `x: T` says “x has the type `T`.”
-
-Multiple arguments can have the same generic type:
-
-```rust
-fn takes_two_of_the_same_things<T>(x: T, y: T) {
-    // ...
-}
-```
-
-We could write a version that takes multiple types:
-
-```rust
-fn takes_two_things<T, U>(x: T, y: U) {
-    // ...
-}
-```
-
-## Generic structs
-
-You can store a generic type in a `struct` as well:
-
-```rust
-struct Point<T> {
-    x: T,
-    y: T,
-}
-
-let int_origin = Point { x: 0, y: 0 };
-let float_origin = Point { x: 0.0, y: 0.0 };
-```
-
-Similar to functions, the `<T>` is where we declare the generic parameters,
-and we then use `x: T` in the type declaration, too.
-
-When you want to add an implementation for the generic `struct`, you
-declare the type parameter after the `impl`:
-
-```rust
-# struct Point<T> {
-#     x: T,
-#     y: T,
-# }
-#
-impl<T> Point<T> {
-    fn swap(&mut self) {
-        std::mem::swap(&mut self.x, &mut self.y);
-    }
-}
-```
-
-So far you’ve seen generics that take absolutely any type. These are useful in
-many cases: you’ve already seen `Option<T>`, and later you’ll meet universal
-container types like [`Vec<T>`][Vec]. On the other hand, often you want to
-trade that flexibility for increased expressive power. Read about [trait
-bounds][traits] to see why and how.
-
-## Resolving ambiguities
-
-Most of the time when generics are involved, the compiler can infer the
-generic parameters automatically:
-
-```rust
-// v must be a Vec<T> but we don't know what T is yet
-let mut v = Vec::new();
-// v just got a bool value, so T must be bool!
-v.push(true);
-// Debug-print v
-println!("{:?}", v);
-```
-
-Sometimes though, the compiler needs a little help. For example, had we
-omitted the last line, we would get a compile error:
-
-```rust,ignore
-let v = Vec::new();
-//      ^^^^^^^^ cannot infer type for `T`
-//
-// note: type annotations or generic parameter binding required
-println!("{:?}", v);
-```
-
-We can solve this using either a type annotation:
-
-```rust
-let v: Vec<bool> = Vec::new();
-println!("{:?}", v);
-```
-
-or by binding the generic parameter `T` via the so-called
-[‘turbofish’][turbofish] `::<>` syntax:
-
-```rust
-let v = Vec::<bool>::new();
-println!("{:?}", v);
-```
-
-The second approach is useful in situations where we don’t want to bind the
-result to a variable. It can also be used to bind generic parameters in
-functions or methods. See [Iterators § Consumers](iterators.html#consumers)
-for an example.
-
-[traits]: traits.html
-[Vec]: ../std/vec/struct.Vec.html
-[turbofish]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect
diff --git a/src/doc/book/src/getting-started.md b/src/doc/book/src/getting-started.md
deleted file mode 100644 (file)
index 06ea24f..0000000
+++ /dev/null
@@ -1,550 +0,0 @@
-# Getting Started
-
-This first chapter of the book will get us going with Rust and its tooling.
-First, we’ll install Rust. Then, the classic ‘Hello World’ program. Finally,
-we’ll talk about Cargo, Rust’s build system and package manager.
-
-We’ll be showing off a number of commands using a terminal, and those lines all
-start with `$`. You don't need to type in the `$`s, they are there to indicate
-the start of each command. We’ll see many tutorials and examples around the web
-that follow this convention: `$` for commands run as our regular user, and `#`
-for commands we should be running as an administrator.
-
-# Installing Rust
-
-The first step to using Rust is to install it. Generally speaking, you’ll need
-an Internet connection to run the commands in this section, as we’ll be
-downloading Rust from the Internet.
-
-The Rust compiler runs on, and compiles to, a great number of platforms, but is
-best supported on Linux, Mac, and Windows, on the x86 and x86-64 CPU
-architecture. There are official builds of the Rust compiler and standard
-library for these platforms and more. [For full details on Rust platform support
-see the website][platform-support].
-
-[platform-support]: https://forge.rust-lang.org/platform-support.html
-
-## Installing Rust
-
-All you need to do on Unix systems like Linux and macOS is open a
-terminal and type this:
-
-```bash
-$ curl https://sh.rustup.rs -sSf | sh
-```
-
-It will download a script, and start the installation. If everything
-goes well, you’ll see this appear:
-
-```text
-Rust is installed now. Great! 
-```
-
-Installing on Windows is nearly as easy: download and run
-[rustup-init.exe]. It will start the installation in a console and
-present the above message on success.
-
-For other installation options and information, visit the [install]
-page of the Rust website.
-
-[rustup-init.exe]: https://win.rustup.rs
-[install]: https://www.rust-lang.org/install.html
-
-## Uninstalling
-
-Uninstalling Rust is as easy as installing it:
-
-```bash
-$ rustup self uninstall
-```
-
-## Troubleshooting
-
-If we've got Rust installed, we can open up a shell, and type this:
-
-```bash
-$ rustc --version
-```
-
-You should see the version number, commit hash, and commit date.
-
-If you do, Rust has been installed successfully! Congrats!
-
-If you don't, that probably means that the `PATH` environment variable
-doesn't include Cargo's binary directory, `~/.cargo/bin` on Unix, or
-`%USERPROFILE%\.cargo\bin` on Windows. This is the directory where
-Rust development tools live, and most Rust developers keep it in their
-`PATH` environment variable, which makes it possible to run `rustc` on
-the command line. Due to differences in operating systems, command
-shells, and bugs in installation, you may need to restart your shell,
-log out of the system, or configure `PATH` manually as appropriate for
-your operating environment.
-
-Rust does not do its own linking, and so you’ll need to have a linker
-installed. Doing so will depend on your specific system. For
-Linux-based systems, Rust will attempt to call `cc` for linking. On
-`windows-msvc` (Rust built on Windows with Microsoft Visual Studio),
-this depends on having [Microsoft Visual C++ Build Tools][msvbt]
-installed. These do not need to be in `%PATH%` as `rustc` will find
-them automatically. In general, if you have your linker in a
-non-traditional location you can call `rustc 
-linker=/path/to/cc`, where `/path/to/cc` should point to your linker path.
-
-[msvbt]: http://landinghub.visualstudio.com/visual-cpp-build-tools
-
-If you are still stuck, there are a number of places where we can get
-help. The easiest is
-[the #rust-beginners IRC channel on irc.mozilla.org][irc-beginners] 
-and for general discussion
-[the #rust IRC channel on irc.mozilla.org][irc], which we 
-can access through [Mibbit][mibbit]. Then we'll be chatting with other
-Rustaceans (a silly nickname we call ourselves) who can help us out. Other great
-resources include [the user’s forum][users] and [Stack Overflow][stackoverflow].
-
-[irc-beginners]: irc://irc.mozilla.org/#rust-beginners
-[irc]: irc://irc.mozilla.org/#rust
-[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-beginners,%23rust
-[users]: https://users.rust-lang.org/
-[stackoverflow]: http://stackoverflow.com/questions/tagged/rust
-
-This installer also installs a copy of the documentation locally, so we can
-read it offline. It's only a `rustup doc` away!
-
-# Hello, world!
-
-Now that you have Rust installed, we'll help you write your first Rust program.
-It's traditional when learning a new language to write a little program to
-print the text “Hello, world!” to the screen, and in this section, we'll follow
-that tradition.
-
-The nice thing about starting with such a simple program is that you can
-quickly verify that your compiler is installed, and that it's working properly.
-Printing information to the screen is also a pretty common thing to do, so
-practicing it early on is good.
-
-> Note: This book assumes basic familiarity with the command line. Rust itself
-> makes no specific demands about your editing, tooling, or where your code
-> lives, so if you prefer an IDE to the command line, that's an option. You may
-> want to check out [SolidOak], which was built specifically with Rust in mind.
-> There are a number of extensions in development by the community, and the
-> Rust team ships plugins for [various editors]. Configuring your editor or
-> IDE is out of the scope of this tutorial, so check the documentation for your
-> specific setup.
-
-[SolidOak]: https://github.com/oakes/SolidOak
-[various editors]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md
-
-## Creating a Project File
-
-First, make a file to put your Rust code in. Rust doesn't care where your code
-lives, but for this book, I suggest making a *projects* directory in your home
-directory, and keeping all your projects there. Open a terminal and enter the
-following commands to make a directory for this particular project:
-
-```bash
-$ mkdir ~/projects
-$ cd ~/projects
-$ mkdir hello_world
-$ cd hello_world
-```
-
-> Note: If you’re on Windows and not using PowerShell, the `~` may not work.
-> Consult the documentation for your shell for more details.
-
-## Writing and Running a Rust Program
-
-We need to create a source file for our Rust program. Rust files always end
-in a *.rs* extension. If you are using more than one word in your filename,
-use an underscore to separate them; for example, you would use
-*my_program.rs* rather than *myprogram.rs*.
-
-Now, make a new file and call it *main.rs*. Open the file and type
-the following code:
-
-```rust
-fn main() {
-    println!("Hello, world!");
-}
-```
-
-Save the file, and go back to your terminal window. On Linux or macOS, enter the
-following commands:
-
-```bash
-$ rustc main.rs
-$ ./main
-Hello, world!
-```
-
-In Windows, replace `main` with `main.exe`. Regardless of your operating
-system, you should see the string `Hello, world!` print to the terminal. If you
-did, then congratulations! You've officially written a Rust program. That makes
-you a Rust programmer! Welcome.
-
-## Anatomy of a Rust Program
-
-Now, let’s go over what just happened in your "Hello, world!" program in
-detail. Here's the first piece of the puzzle:
-
-```rust
-fn main() {
-
-}
-```
-
-These lines define a *function* in Rust. The `main` function is special: it's
-the beginning of every Rust program. The first line says, “I’m declaring a
-function named `main` that takes no arguments and returns nothing.” If there
-were arguments, they would go inside the parentheses (`(` and `)`), and because
-we aren’t returning anything from this function, we can omit the return type
-entirely.
-
-Also note that the function body is wrapped in curly braces (`{` and `}`). Rust
-requires these around all function bodies. It's considered good style to put
-the opening curly brace on the same line as the function declaration, with one
-space in between.
-
-Inside the `main()` function:
-
-```rust
-    println!("Hello, world!");
-```
-
-This line does all of the work in this little program: it prints text to the
-screen. There are a number of details that are important here. The first is
-that it’s indented with four spaces, not tabs.
-
-The second important part is the `println!()` line. This is calling a Rust
-*[macro]*, which is how metaprogramming is done in Rust. If it were calling a
-function instead, it would look like this: `println()` (without the !). We'll
-discuss Rust macros in more detail later, but for now you only need to
-know that when you see a `!` that means that you’re calling a macro instead of
-a normal function.
-
-
-[macro]: macros.html
-
-Next is `"Hello, world!"` which is a *string*. Strings are a surprisingly
-complicated topic in a systems programming language, and this is a *[statically
-allocated]* string. We pass this string as an argument to `println!`, which
-prints the string to the screen. Easy enough!
-
-[statically allocated]: the-stack-and-the-heap.html
-
-The line ends with a semicolon (`;`). Rust is an *[expression-oriented
-language]*, which means that most things are expressions, rather than
-statements. The `;` indicates that this expression is over, and the next one is
-ready to begin. Most lines of Rust code end with a `;`.
-
-[expression-oriented language]: glossary.html#expression-oriented-language
-
-## Compiling and Running Are Separate Steps
-
-In "Writing and Running a Rust Program", we showed you how to run a newly
-created program. We'll break that process down and examine each step now.
-
-Before running a Rust program, you have to compile it. You can use the Rust
-compiler by entering the `rustc` command and passing it the name of your source
-file, like this:
-
-```bash
-$ rustc main.rs
-```
-
-If you come from a C or C++ background, you'll notice that this is similar to
-`gcc` or `clang`. After compiling successfully, Rust should output a binary
-executable, which you can see on Linux or macOS by entering the `ls` command in
-your shell as follows:
-
-```bash
-$ ls
-main  main.rs
-```
-
-On Windows, you'd enter:
-
-```bash
-$ dir
-main.exe
-main.rs
-```
-
-This shows we have two files: the source code, with an `.rs` extension, and the
-executable (`main.exe` on Windows, `main` everywhere else). All that's left to
-do from here is run the `main` or `main.exe` file, like this:
-
-```bash
-$ ./main  # or .\main.exe on Windows
-```
-
-If *main.rs* were your "Hello, world!" program, this would print `Hello,
-world!` to your terminal.
-
-If you come from a dynamic language like Ruby, Python, or JavaScript, you may
-not be used to compiling and running a program being separate steps. Rust is an
-*ahead-of-time compiled* language, which means that you can compile a program,
-give it to someone else, and they can run it even without Rust installed. If
-you give someone a `.rb` or `.py` or `.js` file, on the other hand, they need
-to have a Ruby, Python, or JavaScript implementation installed (respectively),
-but you only need one command to both compile and run your program. Everything
-is a tradeoff in language design.
-
-Just compiling with `rustc` is fine for simple programs, but as your project
-grows, you'll want to be able to manage all of the options your project has,
-and make it easy to share your code with other people and projects. Next, I'll
-introduce you to a tool called Cargo, which will help you write real-world Rust
-programs.
-
-# Hello, Cargo!
-
-Cargo is Rust’s build system and package manager, and Rustaceans use Cargo to
-manage their Rust projects. Cargo manages three things: building your code,
-downloading the libraries your code depends on, and building those libraries.
-We call libraries your code needs ‘dependencies’ since your code depends on
-them.
-
-The simplest Rust programs don’t have any dependencies, so right now, you'd
-only use the first part of its functionality. As you write more complex Rust
-programs, you’ll want to add dependencies, and if you start off using Cargo,
-that will be a lot easier to do.
-
-As the vast, vast majority of Rust projects use Cargo, we will assume that
-you’re using it for the rest of the book. Cargo comes installed with Rust
-itself, if you used the official installers. If you installed Rust through some
-other means, you can check if you have Cargo installed by typing:
-
-```bash
-$ cargo --version
-```
-
-Into a terminal. If you see a version number, great! If you see an error like
-‘`command not found`’, then you should look at the documentation for the system
-in which you installed Rust, to determine if Cargo is separate.
-
-## Converting to Cargo
-
-Let’s convert the Hello World program to Cargo. To Cargo-fy a project, you need
-to do three things:
-
-1. Put your source file in the right directory.
-2. Get rid of the old executable (`main.exe` on Windows, `main` everywhere
-   else).
-3. Make a Cargo configuration file.
-
-Let's get started!
-
-### Creating a Source Directory and Removing the Old Executable
-
-First, go back to your terminal, move to your *hello_world* directory, and
-enter the following commands:
-
-```bash
-$ mkdir src
-$ mv main.rs src/main.rs # or 'move main.rs src/main.rs' on Windows
-$ rm main  # or 'del main.exe' on Windows
-```
-
-Cargo expects your source files to live inside a *src* directory, so do that
-first. This leaves the top-level project directory (in this case,
-*hello_world*) for READMEs, license information, and anything else not related
-to your code. In this way, using Cargo helps you keep your projects nice and
-tidy. There's a place for everything, and everything is in its place.
-
-Now, move *main.rs* into the *src* directory, and delete the compiled file you
-created with `rustc`. As usual, replace `main` with `main.exe` if you're on
-Windows.
-
-This example retains `main.rs` as the source filename because it's creating an
-executable. If you wanted to make a library instead, you'd name the file
-`lib.rs`. This convention is used by Cargo to successfully compile your
-projects, but it can be overridden if you wish.
-
-### Creating a Configuration File
-
-Next, create a new file inside your *hello_world* directory, and call it
-`Cargo.toml`.
-
-Make sure to capitalize the `C` in `Cargo.toml`, or Cargo won't know what to do
-with the configuration file.
-
-This file is in the *[TOML]* (Tom's Obvious, Minimal Language) format. TOML is
-similar to INI, but has some extra goodies, and is used as Cargo’s
-configuration format.
-
-[TOML]: https://github.com/toml-lang/toml
-
-Inside this file, type the following information:
-
-```toml
-[package]
-
-name = "hello_world"
-version = "0.0.1"
-authors = [ "Your name <you@example.com>" ]
-```
-
-The first line, `[package]`, indicates that the following statements are
-configuring a package. As we add more information to this file, we’ll add other
-sections, but for now, we only have the package configuration.
-
-The other three lines set the three bits of configuration that Cargo needs to
-know to compile your program: its name, what version it is, and who wrote it.
-
-Once you've added this information to the *Cargo.toml* file, save it to finish
-creating the configuration file.
-
-## Building and Running a Cargo Project
-
-With your *Cargo.toml* file in place in your project's root directory, you
-should be ready to build and run your Hello World program! To do so, enter the
-following commands:
-
-```bash
-$ cargo build
-   Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
-$ ./target/debug/hello_world
-Hello, world!
-```
-
-Bam! If all goes well, `Hello, world!` should print to the terminal once more.
-
-You just built a project with `cargo build` and ran it with
-`./target/debug/hello_world`, but you can actually do both in one step with
-`cargo run` as follows:
-
-```bash
-$ cargo run
-     Running `target/debug/hello_world`
-Hello, world!
-```
-
-The `run` command comes in handy when you need to rapidly iterate on a
-project.
-
-Notice that this example didn’t re-build the project. Cargo figured out that
-the file hasn’t changed, and so it just ran the binary. If you'd modified your
-source code, Cargo would have rebuilt the project before running it, and you
-would have seen something like this:
-
-```bash
-$ cargo run
-   Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
-     Running `target/debug/hello_world`
-Hello, world!
-```
-
-Cargo checks to see if any of your project’s files have been modified, and only
-rebuilds your project if they’ve changed since the last time you built it.
-
-With simple projects, Cargo doesn't bring a whole lot over just using `rustc`,
-but it will become useful in the future. This is especially true when you start
-using crates; these are synonymous with a ‘library’ or ‘package’ in other
-programming languages. For complex projects composed of multiple crates, it’s
-much easier to let Cargo coordinate the build. Using Cargo, you can run `cargo
-build`, and it should work the right way.
-
-### Building for Release
-
-When your project is ready for release, you can use `cargo build
---release` to compile your project with optimizations. These optimizations make
-your Rust code run faster, but turning them on makes your program take longer
-to compile. This is why there are two different profiles, one for development,
-and one for building the final program you’ll give to a user.
-
-### What Is That `Cargo.lock`?
-
-Running `cargo build` also causes Cargo to create a new file called
-*Cargo.lock*, which looks like this:
-
-```toml
-[root]
-name = "hello_world"
-version = "0.0.1"
-```
-
-Cargo uses the *Cargo.lock* file to keep track of dependencies in your
-application. This is the Hello World project's *Cargo.lock* file. This project
-doesn't have dependencies, so the file is a bit sparse. Realistically, you
-won't ever need to touch this file yourself; just let Cargo handle it.
-
-That’s it! If you've been following along, you should have successfully built
-`hello_world` with Cargo.
-
-Even though the project is simple, it now uses much of the real tooling you’ll
-use for the rest of your Rust career. In fact, you can expect to start
-virtually all Rust projects with some variation on the following commands:
-
-```bash
-$ git clone someurl.com/foo
-$ cd foo
-$ cargo build
-```
-
-## Making A New Cargo Project the Easy Way
-
-You don’t have to go through that previous process every time you want to start
-a new project! Cargo can quickly make a bare-bones project directory that you
-can start developing in right away.
-
-To start a new project with Cargo, enter `cargo new` at the command line:
-
-```bash
-$ cargo new hello_world --bin
-```
-
-This command passes `--bin` because the goal is to get straight to making an
-executable application, as opposed to a library. Executables are often called
-*binaries* (as in `/usr/bin`, if you’re on a Unix system).
-
-Cargo has generated two files and one directory for us: a `Cargo.toml` and a
-*src* directory with a *main.rs* file inside. These should look familiar,
-they’re exactly what we created by hand, above.
-
-This output is all you need to get started. First, open `Cargo.toml`. It should
-look something like this:
-
-```toml
-[package]
-
-name = "hello_world"
-version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
-
-[dependencies]
-```
-
-Do not worry about the `[dependencies]` line, we will come back to it later.
-
-Cargo has populated *Cargo.toml* with reasonable defaults based on the arguments
-you gave it and your `git` global configuration. You may notice that Cargo has
-also initialized the `hello_world` directory as a `git` repository.
-
-Here’s what should be in `src/main.rs`:
-
-```rust
-fn main() {
-    println!("Hello, world!");
-}
-```
-
-Cargo has generated a "Hello World!" for you, and you’re ready to start coding!
-
-> Note: If you want to look at Cargo in more detail, check out the official [Cargo
-guide], which covers all of its features.
-
-[Cargo guide]: http://doc.crates.io/guide.html
-
-# Closing Thoughts
-
-This chapter covered the basics that will serve you well through the rest of
-this book, and the rest of your time with Rust. Now that you’ve got the tools
-down, we'll cover more about the Rust language itself.
-
-You have two options: Dive into a project with ‘[Tutorial: Guessing Game][guessinggame]’, or
-start from the bottom and work your way up with ‘[Syntax and
-Semantics][syntax]’. More experienced systems programmers will probably prefer
-‘Tutorial: Guessing Game’, while those from dynamic backgrounds may enjoy either. Different
-people learn differently! Choose whatever’s right for you.
-
-[guessinggame]: guessing-game.html
-[syntax]: syntax-and-semantics.html
diff --git a/src/doc/book/src/glossary.md b/src/doc/book/src/glossary.md
deleted file mode 100644 (file)
index b17b896..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-# Glossary
-
-Not every Rustacean has a background in systems programming, nor in computer
-science, so we've added explanations of terms that might be unfamiliar.
-
-### Abstract Syntax Tree
-
-When a compiler is compiling your program, it does a number of different things.
-One of the things that it does is turn the text of your program into an
-‘abstract syntax tree’, or ‘AST’. This tree is a representation of the structure
-of your program. For example, `2 + 3` can be turned into a tree:
-
-```text
-  +
- / \
-2   3
-```
-
-And `2 + (3 * 4)` would look like this:
-
-```text
-  +
- / \
-2   *
-   / \
-  3   4
-```
-
-### Arity
-
-Arity refers to the number of arguments a function or operation takes.
-
-```rust
-let x = (2, 3);
-let y = (4, 6);
-let z = (8, 2, 6);
-```
-
-In the example above `x` and `y` have arity 2. `z` has arity 3.
-
-### Bounds
-
-Bounds are constraints on a type or [trait][traits]. For example, if a bound
-is placed on the argument a function takes, types passed to that function
-must abide by that constraint.
-
-[traits]: traits.html
-
-### Combinators
-
-Combinators are higher-order functions that apply only functions and
-earlier defined combinators to provide a result from its arguments. 
-They can be used to manage control flow in a modular fashion.
-
-### DST (Dynamically Sized Type)
-
-A type without a statically known size or alignment. ([more info][link])
-
-[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-dsts
-
-### Expression
-
-In computer programming, an expression is a combination of values, constants,
-variables, operators and functions that evaluate to a single value. For example,
-`2 + (3 * 4)` is an expression that returns the value 14. It is worth noting
-that expressions can have side-effects. For example, a function included in an
-expression might perform actions other than simply returning a value.
-
-### Expression-Oriented Language
-
-In early programming languages, [expressions][expression] and
-[statements][statement] were two separate syntactic categories: expressions had
-a value and statements did things. However, later languages blurred this
-distinction, allowing expressions to do things and statements to have a value.
-In an expression-oriented language, (nearly) every statement is an expression
-and therefore returns a value. Consequently, these expression statements can
-themselves form part of larger expressions.
-
-[expression]: glossary.html#expression
-[statement]: glossary.html#statement
-
-### Statement
-
-In computer programming, a statement is the smallest standalone element of a
-programming language that commands a computer to perform an action.
diff --git a/src/doc/book/src/guessing-game.md b/src/doc/book/src/guessing-game.md
deleted file mode 100644 (file)
index bbb43b4..0000000
+++ /dev/null
@@ -1,1010 +0,0 @@
-# Guessing Game
-
-Let’s learn some Rust! For our first project, we’ll implement a classic
-beginner programming problem: the guessing game. Here’s how it works: Our
-program will generate a random integer between one and a hundred. It will then
-prompt us to enter a guess. Upon entering our guess, it will tell us if we’re
-too low or too high. Once we guess correctly, it will congratulate us. Sounds
-good?
-
-Along the way, we’ll learn a little bit about Rust. The next chapter, ‘Syntax
-and Semantics’, will dive deeper into each part.
-
-# Set up
-
-Let’s set up a new project. Go to your projects directory. Remember how we had
-to create our directory structure and a `Cargo.toml` for `hello_world`? Cargo
-has a command that does that for us. Let’s give it a shot:
-
-```bash
-$ cd ~/projects
-$ cargo new guessing_game --bin
-     Created binary (application) `guessing_game` project
-$ cd guessing_game
-```
-
-We pass the name of our project to `cargo new`, and then the `--bin` flag,
-since we’re making a binary, rather than a library.
-
-Check out the generated `Cargo.toml`:
-
-```toml
-[package]
-
-name = "guessing_game"
-version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
-```
-
-Cargo gets this information from your environment. If it’s not correct, go ahead
-and fix that.
-
-Finally, Cargo generated a ‘Hello, world!’ for us. Check out `src/main.rs`:
-
-```rust
-fn main() {
-    println!("Hello, world!");
-}
-```
-
-Let’s try compiling what Cargo gave us:
-
-```{bash}
-$ cargo build
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.53 secs
-```
-
-Excellent! Open up your `src/main.rs` again. We’ll be writing all of
-our code in this file.
-
-Remember the `run` command from last chapter? Try it out again here:
-
-```bash
-$ cargo run
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
-     Running `target/debug/guessing_game`
-Hello, world!
-```
-
-Great! Our game is just the kind of project `run` is good for: we need
-to quickly test each iteration before moving on to the next one.
-
-# Processing a Guess
-
-Let’s get to it! The first thing we need to do for our guessing game is
-allow our player to input a guess. Put this in your `src/main.rs`:
-
-```rust,no_run
-use std::io;
-
-fn main() {
-    println!("Guess the number!");
-
-    println!("Please input your guess.");
-
-    let mut guess = String::new();
-
-    io::stdin().read_line(&mut guess)
-        .expect("Failed to read line");
-
-    println!("You guessed: {}", guess);
-}
-```
-
-There’s a lot here! Let’s go over it, bit by bit.
-
-```rust,ignore
-use std::io;
-```
-
-We’ll need to take user input, and then print the result as output. As such, we
-need the `io` library from the standard library. Rust only imports a few things
-by default into every program, [the ‘prelude’][prelude]. If it’s not in the
-prelude, you’ll have to `use` it directly. There is also a second ‘prelude’, the
-[`io` prelude][ioprelude], which serves a similar function: you import it, and it
-imports a number of useful, `io`-related things.
-
-[prelude]: ../std/prelude/index.html
-[ioprelude]: ../std/io/prelude/index.html
-
-```rust,ignore
-fn main() {
-```
-
-As you’ve seen before, the `main()` function is the entry point into your
-program. The `fn` syntax declares a new function, the `()`s indicate that
-there are no arguments, and `{` starts the body of the function. Because
-we didn’t include a return type, it’s assumed to be `()`, an empty
-[tuple][tuples].
-
-[tuples]: primitive-types.html#tuples
-
-```rust,ignore
-    println!("Guess the number!");
-
-    println!("Please input your guess.");
-```
-
-We previously learned that `println!()` is a [macro][macros] that
-prints a [string][strings] to the screen.
-
-[macros]: macros.html
-[strings]: strings.html
-
-```rust,ignore
-    let mut guess = String::new();
-```
-
-Now we’re getting interesting! There’s a lot going on in this little line.
-The first thing to notice is that this is a [let statement][let], which is
-used to create ‘variable bindings’. They take this form:
-
-```rust,ignore
-let foo = bar;
-```
-
-[let]: variable-bindings.html
-
-This will create a new binding named `foo`, and bind it to the value `bar`. In
-many languages, this is called a ‘variable’, but Rust’s variable bindings have
-a few tricks up their sleeves.
-
-For example, they’re [immutable][immutable] by default. That’s why our example
-uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t
-take a name on the left hand side of the assignment, it actually accepts a
-‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough
-to use for now:
-
-```rust
-let foo = 5; // `foo` is immutable.
-let mut bar = 5; // `bar` is mutable.
-```
-
-[immutable]: mutability.html
-[patterns]: patterns.html
-
-Oh, and `//` will start a comment, until the end of the line. Rust ignores
-everything in [comments][comments].
-
-[comments]: comments.html
-
-So now we know that `let mut guess` will introduce a mutable binding named
-`guess`, but we have to look at the other side of the `=` for what it’s
-bound to: `String::new()`.
-
-`String` is a string type, provided by the standard library. A
-[`String`][string] is a growable, UTF-8 encoded bit of text.
-
-[string]: ../std/string/struct.String.html
-
-The `::new()` syntax uses `::` because this is an ‘associated function’ of
-a particular type. That is to say, it’s associated with `String` itself,
-rather than a particular instance of a `String`. Some languages call this a
-‘static method’.
-
-This function is named `new()`, because it creates a new, empty `String`.
-You’ll find a `new()` function on many types, as it’s a common name for making
-a new value of some kind.
-
-Let’s move forward:
-
-```rust,ignore
-    io::stdin().read_line(&mut guess)
-        .expect("Failed to read line");
-```
-
-That’s a lot more! Let’s go bit-by-bit. The first line has two parts. Here’s
-the first:
-
-```rust,ignore
-io::stdin()
-```
-
-Remember how we `use`d `std::io` on the first line of the program? We’re now
-calling an associated function on it. If we didn’t `use std::io`, we could
-have written this line as `std::io::stdin()`.
-
-This particular function returns a handle to the standard input for your
-terminal. More specifically, a [std::io::Stdin][iostdin].
-
-[iostdin]: ../std/io/struct.Stdin.html
-
-The next part will use this handle to get input from the user:
-
-```rust,ignore
-.read_line(&mut guess)
-```
-
-Here, we call the [`read_line`][read_line] method on our handle.
-[Methods][method] are like associated functions, but are only available on a
-particular instance of a type, rather than the type itself. We’re also passing
-one argument to `read_line()`: `&mut guess`.
-
-[read_line]: ../std/io/struct.Stdin.html#method.read_line
-[method]: method-syntax.html
-
-Remember how we bound `guess` above? We said it was mutable. However,
-`read_line` doesn’t take a `String` as an argument: it takes a `&mut String`.
-Rust has a feature called ‘[references][references]’, which allows you to have
-multiple references to one piece of data, which can reduce copying. References
-are a complex feature, as one of Rust’s major selling points is how safe and
-easy it is to use references. We don’t need to know a lot of those details to
-finish our program right now, though. For now, all we need to know is that
-like `let` bindings, references are immutable by default. Hence, we need to
-write `&mut guess`, rather than `&guess`.
-
-Why does `read_line()` take a mutable reference to a string? Its job is
-to take what the user types into standard input, and place that into a
-string. So it takes that string as an argument, and in order to add
-the input, it needs to be mutable.
-
-[references]: references-and-borrowing.html
-
-But we’re not quite done with this line of code, though. While it’s
-a single line of text, it’s only the first part of the single logical line of
-code:
-
-```rust,ignore
-        .expect("Failed to read line");
-```
-
-When you call a method with the `.foo()` syntax, you may introduce a newline
-and other whitespace. This helps you split up long lines. We _could_ have
-done:
-
-```rust,ignore
-    io::stdin().read_line(&mut guess).expect("Failed to read line");
-```
-
-But that gets hard to read. So we’ve split it up, two lines for two method
-calls. We already talked about `read_line()`, but what about `expect()`? Well,
-we already mentioned that `read_line()` puts what the user types into the `&mut
-String` we pass it. But it also returns a value: in this case, an
-[`io::Result`][ioresult]. Rust has a number of types named `Result` in its
-standard library: a generic [`Result`][result], and then specific versions for
-sub-libraries, like `io::Result`.
-
-[ioresult]: ../std/io/type.Result.html
-[result]: ../std/result/enum.Result.html
-
-The purpose of these `Result` types is to encode error handling information.
-Values of the `Result` type, like any type, have methods defined on them. In
-this case, `io::Result` has an [`expect()` method][expect] that takes a value
-it’s called on, and if it isn’t a successful one, [`panic!`][panic]s with a
-message you passed it. A `panic!` like this will cause our program to crash,
-displaying the message.
-
-[expect]: ../std/result/enum.Result.html#method.expect
-[panic]: error-handling.html
-
-If we do not call `expect()`, our program will compile, but
-we’ll get a warning:
-
-```bash
-$ cargo build
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-warning: unused result which must be used, #[warn(unused_must_use)] on by default
-  --> src/main.rs:10:5
-   |
-10 |     io::stdin().read_line(&mut guess);
-   |     ^
-
-    Finished debug [unoptimized + debuginfo] target(s) in 0.42 secs
-```
-
-Rust warns us that we haven’t used the `Result` value. This warning comes from
-a special annotation that `io::Result` has. Rust is trying to tell you that
-you haven’t handled a possible error. The right way to suppress the error is
-to actually write error handling. Luckily, if we want to crash if there’s
-a problem, we can use `expect()`. If we can recover from the
-error somehow, we’d do something else, but we’ll save that for a future
-project.
-
-There’s only one line of this first example left:
-
-```rust,ignore
-    println!("You guessed: {}", guess);
-}
-```
-
-This prints out the string we saved our input in. The `{}`s are a placeholder,
-and so we pass it `guess` as an argument. If we had multiple `{}`s, we would
-pass multiple arguments:
-
-```rust
-let x = 5;
-let y = 10;
-
-println!("x and y: {} and {}", x, y);
-```
-
-Easy.
-
-Anyway, that’s the tour. We can run what we have with `cargo run`:
-
-```bash
-$ cargo run
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.44 secs
-     Running `target/debug/guessing_game`
-Guess the number!
-Please input your guess.
-6
-You guessed: 6
-```
-
-All right! Our first part is done: we can get input from the keyboard,
-and then print it back out.
-
-# Generating a secret number
-
-Next, we need to generate a secret number. Rust does not yet include random
-number functionality in its standard library. The Rust team does, however,
-provide a [`rand` crate][randcrate]. A ‘crate’ is a package of Rust code.
-We’ve been building a ‘binary crate’, which is an executable. `rand` is a
-‘library crate’, which contains code that’s intended to be used with other
-programs.
-
-[randcrate]: https://crates.io/crates/rand
-
-Using external crates is where Cargo really shines. Before we can write
-the code using `rand`, we need to modify our `Cargo.toml`. Open it up, and
-add these few lines at the bottom:
-
-```toml
-[dependencies]
-
-rand="0.3.0"
-```
-
-The `[dependencies]` section of `Cargo.toml` is like the `[package]` section:
-everything that follows it is part of it, until the next section starts.
-Cargo uses the dependencies section to know what dependencies on external
-crates you have, and what versions you require. In this case, we’ve specified version `0.3.0`,
-which Cargo understands to be any release that’s compatible with this specific version.
-Cargo understands [Semantic Versioning][semver], which is a standard for writing version
-numbers. A bare number like above is actually shorthand for `^0.3.0`,
-meaning "anything compatible with 0.3.0".
-If we wanted to use only `0.3.0` exactly, we could say `rand="=0.3.0"`
-(note the two equal signs).
-We could also use a range of versions.
-[Cargo’s documentation][cargodoc] contains more details.
-
-[semver]: http://semver.org
-[cargodoc]: http://doc.crates.io/specifying-dependencies.html
-
-Now, without changing any of our code, let’s build our project:
-
-```bash
-$ cargo build
-    Updating registry `https://github.com/rust-lang/crates.io-index`
- Downloading rand v0.3.14
- Downloading libc v0.2.17
-   Compiling libc v0.2.17
-   Compiling rand v0.3.14
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-    Finished debug [unoptimized + debuginfo] target(s) in 5.88 secs
-```
-
-(You may see different versions, of course.)
-
-Lots of new output! Now that we have an external dependency, Cargo fetches the
-latest versions of everything from the registry, which is a copy of data from
-[Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem
-post their open source Rust projects for others to use.
-
-[cratesio]: https://crates.io
-
-After updating the registry, Cargo checks our `[dependencies]` and downloads
-any we don’t have yet. In this case, while we only said we wanted to depend on
-`rand`, we’ve also grabbed a copy of `libc`. This is because `rand` depends on
-`libc` to work. After downloading them, it compiles them, and then compiles
-our project.
-
-If we run `cargo build` again, we’ll get different output:
-
-```bash
-$ cargo build
-    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
-```
-
-That’s right, nothing was done! Cargo knows that our project has been built, and that
-all of its dependencies are built, and so there’s no reason to do all that
-stuff. With nothing to do, it simply exits. If we open up `src/main.rs` again,
-make a trivial change, and then save it again, we’ll only see two lines:
-
-```bash
-$ cargo build
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.45 secs
-```
-
-So, we told Cargo we wanted any `0.3.x` version of `rand`, and so it fetched the latest
-version at the time this was written, `v0.3.14`. But what happens when next
-week, version `v0.3.15` comes out, with an important bugfix? While getting
-bugfixes is important, what if `0.3.15` contains a regression that breaks our
-code?
-
-The answer to this problem is the `Cargo.lock` file you’ll now find in your
-project directory. When you build your project for the first time, Cargo
-figures out all of the versions that fit your criteria, and then writes them
-to the `Cargo.lock` file. When you build your project in the future, Cargo
-will see that the `Cargo.lock` file exists, and then use that specific version
-rather than do all the work of figuring out versions again. This lets you
-have a repeatable build automatically. In other words, we’ll stay at `0.3.14`
-until we explicitly upgrade, and so will anyone who we share our code with,
-thanks to the lock file.
-
-What about when we _do_ want to use `v0.3.15`? Cargo has another command,
-`update`, which says ‘ignore the lock, figure out all the latest versions that
-fit what we’ve specified. If that works, write those versions out to the lock
-file’. But, by default, Cargo will only look for versions larger than `0.3.0`
-and smaller than `0.4.0`. If we want to move to `0.4.x`, we’d have to update
-the `Cargo.toml` directly. When we do, the next time we `cargo build`, Cargo
-will update the index and re-evaluate our `rand` requirements.
-
-There’s a lot more to say about [Cargo][doccargo] and [its
-ecosystem][doccratesio], but for now, that’s all we need to know. Cargo makes
-it really easy to re-use libraries, and so Rustaceans tend to write smaller
-projects which are assembled out of a number of sub-packages.
-
-[doccargo]: http://doc.crates.io
-[doccratesio]: http://doc.crates.io/crates-io.html
-
-Let’s get on to actually _using_ `rand`. Here’s our next step:
-
-```rust,ignore
-extern crate rand;
-
-use std::io;
-use rand::Rng;
-
-fn main() {
-    println!("Guess the number!");
-
-    let secret_number = rand::thread_rng().gen_range(1, 101);
-
-    println!("The secret number is: {}", secret_number);
-
-    println!("Please input your guess.");
-
-    let mut guess = String::new();
-
-    io::stdin().read_line(&mut guess)
-        .expect("Failed to read line");
-
-    println!("You guessed: {}", guess);
-}
-```
-
-The first thing we’ve done is change the first line. It now says
-`extern crate rand`. Because we declared `rand` in our `[dependencies]`, we
-can use `extern crate` to let Rust know we’ll be making use of it. This also
-does the equivalent of a `use rand;` as well, so we can make use of anything
-in the `rand` crate by prefixing it with `rand::`.
-
-Next, we added another `use` line: `use rand::Rng`. We’re going to use a
-method in a moment, and it requires that `Rng` be in scope to work. The basic
-idea is this: methods are defined on something called ‘traits’, and for the
-method to work, it needs the trait to be in scope. For more about the
-details, read the [traits][traits] section.
-
-[traits]: traits.html
-
-There are two other lines we added, in the middle:
-
-```rust,ignore
-    let secret_number = rand::thread_rng().gen_range(1, 101);
-
-    println!("The secret number is: {}", secret_number);
-```
-
-We use the `rand::thread_rng()` function to get a copy of the random number
-generator, which is local to the particular [thread][concurrency] of execution
-we’re in. Because we `use rand::Rng`’d above, it has a `gen_range()` method
-available. This method takes two arguments, and generates a number between
-them. It’s inclusive on the lower bound, but exclusive on the upper bound,
-so we need `1` and `101` to get a number ranging from one to a hundred.
-
-[concurrency]: concurrency.html
-
-The second line prints out the secret number. This is useful while
-we’re developing our program, so we can easily test it out. But we’ll be
-deleting it for the final version. It’s not much of a game if it prints out
-the answer when you start it up!
-
-Try running our new program a few times:
-
-```bash
-$ cargo run
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.55 secs
-     Running `target/debug/guessing_game`
-Guess the number!
-The secret number is: 7
-Please input your guess.
-4
-You guessed: 4
-$ cargo run
-    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
-     Running `target/debug/guessing_game`
-Guess the number!
-The secret number is: 83
-Please input your guess.
-5
-You guessed: 5
-```
-
-Great! Next up: comparing our guess to the secret number.
-
-# Comparing guesses
-
-Now that we’ve got user input, let’s compare our guess to the secret number.
-Here’s our next step, though it doesn’t quite compile yet:
-
-```rust,ignore
-extern crate rand;
-
-use std::io;
-use std::cmp::Ordering;
-use rand::Rng;
-
-fn main() {
-    println!("Guess the number!");
-
-    let secret_number = rand::thread_rng().gen_range(1, 101);
-
-    println!("The secret number is: {}", secret_number);
-
-    println!("Please input your guess.");
-
-    let mut guess = String::new();
-
-    io::stdin().read_line(&mut guess)
-        .expect("Failed to read line");
-
-    println!("You guessed: {}", guess);
-
-    match guess.cmp(&secret_number) {
-        Ordering::Less    => println!("Too small!"),
-        Ordering::Greater => println!("Too big!"),
-        Ordering::Equal   => println!("You win!"),
-    }
-}
-```
-
-A few new bits here. The first is another `use`. We bring a type called
-`std::cmp::Ordering` into scope. Then, five new lines at the bottom that use
-it:
-
-```rust,ignore
-match guess.cmp(&secret_number) {
-    Ordering::Less    => println!("Too small!"),
-    Ordering::Greater => println!("Too big!"),
-    Ordering::Equal   => println!("You win!"),
-}
-```
-
-The `cmp()` method can be called on anything that can be compared, and it
-takes a reference to the thing you want to compare it to. It returns the
-`Ordering` type we `use`d earlier. We use a [`match`][match] statement to
-determine exactly what kind of `Ordering` it is. `Ordering` is an
-[`enum`][enum], short for ‘enumeration’, which looks like this:
-
-```rust
-enum Foo {
-    Bar,
-    Baz,
-}
-```
-
-[match]: match.html
-[enum]: enums.html
-
-With this definition, anything of type `Foo` can be either a
-`Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the
-namespace for a particular `enum` variant.
-
-The [`Ordering`][ordering] `enum` has three possible variants: `Less`, `Equal`,
-and `Greater`. The `match` statement takes a value of a type, and lets you
-create an ‘arm’ for each possible value. Since we have three types of
-`Ordering`, we have three arms:
-
-```rust,ignore
-match guess.cmp(&secret_number) {
-    Ordering::Less    => println!("Too small!"),
-    Ordering::Greater => println!("Too big!"),
-    Ordering::Equal   => println!("You win!"),
-}
-```
-
-[ordering]: ../std/cmp/enum.Ordering.html
-
-If it’s `Less`, we print `Too small!`, if it’s `Greater`, `Too big!`, and if
-`Equal`, `You win!`. `match` is really useful, and is used often in Rust.
-
-I did mention that this won’t quite compile yet, though. Let’s try it:
-
-```bash
-$ cargo build
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-error[E0308]: mismatched types
-  --> src/main.rs:23:21
-   |
-23 |     match guess.cmp(&secret_number) {
-   |                     ^^^^^^^^^^^^^^ expected struct `std::string::String`, found integral variable
-   |
-   = note: expected type `&std::string::String`
-   = note:    found type `&{integer}`
-
-error: aborting due to previous error
-
-error: Could not compile `guessing_game`.
-
-To learn more, run the command again with --verbose.
-```
-
-Whew! This is a big error. The core of it is that we have ‘mismatched types’.
-Rust has a strong, static type system. However, it also has type inference.
-When we wrote `let guess = String::new()`, Rust was able to infer that `guess`
-should be a `String`, and so it doesn’t make us write out the type. And with
-our `secret_number`, there are a number of types which can have a value
-between one and a hundred: `i32`, a thirty-two-bit number, or `u32`, an
-unsigned thirty-two-bit number, or `i64`, a sixty-four-bit number or others.
-So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here,
-Rust doesn’t know how to compare the `guess` and the `secret_number`. They
-need to be the same type. Ultimately, we want to convert the `String` we
-read as input into a real number type, for comparison. We can do that
-with two more lines. Here’s our new program:
-
-```rust,ignore
-extern crate rand;
-
-use std::io;
-use std::cmp::Ordering;
-use rand::Rng;
-
-fn main() {
-    println!("Guess the number!");
-
-    let secret_number = rand::thread_rng().gen_range(1, 101);
-
-    println!("The secret number is: {}", secret_number);
-
-    println!("Please input your guess.");
-
-    let mut guess = String::new();
-
-    io::stdin().read_line(&mut guess)
-        .expect("Failed to read line");
-
-    let guess: u32 = guess.trim().parse()
-        .expect("Please type a number!");
-
-    println!("You guessed: {}", guess);
-
-    match guess.cmp(&secret_number) {
-        Ordering::Less    => println!("Too small!"),
-        Ordering::Greater => println!("Too big!"),
-        Ordering::Equal   => println!("You win!"),
-    }
-}
-```
-
-The new two lines:
-
-```rust,ignore
-    let guess: u32 = guess.trim().parse()
-        .expect("Please type a number!");
-```
-
-Wait a minute, I thought we already had a `guess`? We do, but Rust allows us
-to ‘shadow’ the previous `guess` with a new one. This is often used in this
-exact situation, where `guess` starts as a `String`, but we want to convert it
-to an `u32`. Shadowing lets us re-use the `guess` name, rather than forcing us
-to come up with two unique names like `guess_str` and `guess`, or something
-else.
-
-We bind `guess` to an expression that looks like something we wrote earlier:
-
-```rust,ignore
-guess.trim().parse()
-```
-
-Here, `guess` refers to the old `guess`, the one that was a `String` with our
-input in it. The `trim()` method on `String`s will eliminate any white space at
-the beginning and end of our string. This is important, as we had to press the
-‘return’ key to satisfy `read_line()`. This means that if we type `5` and hit
-return, `guess` looks like this: `5\n`. The `\n` represents ‘newline’, the
-enter key. `trim()` gets rid of this, leaving our string with only the `5`. The
-[`parse()` method on strings][parse] parses a string into some kind of number.
-Since it can parse a variety of numbers, we need to give Rust a hint as to the
-exact type of number we want. Hence, `let guess: u32`. The colon (`:`) after
-`guess` tells Rust we’re going to annotate its type. `u32` is an unsigned,
-thirty-two bit integer. Rust has [a number of built-in number types][number],
-but we’ve chosen `u32`. It’s a good default choice for a small positive number.
-
-[parse]: ../std/primitive.str.html#method.parse
-[number]: primitive-types.html#numeric-types
-
-Just like `read_line()`, our call to `parse()` could cause an error. What if
-our string contained `A👍%`? There’d be no way to convert that to a number. As
-such, we’ll do the same thing we did with `read_line()`: use the `expect()`
-method to crash if there’s an error.
-
-Let’s try our program out!
-
-```bash
-$ cargo run
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.57 secs
-     Running `target/guessing_game`
-Guess the number!
-The secret number is: 58
-Please input your guess.
-  76
-You guessed: 76
-Too big!
-```
-
-Nice! You can see I even added spaces before my guess, and it still figured
-out that I guessed 76. Run the program a few times, and verify that guessing
-the number works, as well as guessing a number too small.
-
-Now we’ve got most of the game working, but we can only make one guess. Let’s
-change that by adding loops!
-
-# Looping
-
-The `loop` keyword gives us an infinite loop. Let’s add that in:
-
-```rust,ignore
-extern crate rand;
-
-use std::io;
-use std::cmp::Ordering;
-use rand::Rng;
-
-fn main() {
-    println!("Guess the number!");
-
-    let secret_number = rand::thread_rng().gen_range(1, 101);
-
-    println!("The secret number is: {}", secret_number);
-
-    loop {
-        println!("Please input your guess.");
-
-        let mut guess = String::new();
-
-        io::stdin().read_line(&mut guess)
-            .expect("Failed to read line");
-
-        let guess: u32 = guess.trim().parse()
-            .expect("Please type a number!");
-
-        println!("You guessed: {}", guess);
-
-        match guess.cmp(&secret_number) {
-            Ordering::Less    => println!("Too small!"),
-            Ordering::Greater => println!("Too big!"),
-            Ordering::Equal   => println!("You win!"),
-        }
-    }
-}
-```
-
-And try it out. But wait, didn’t we just add an infinite loop? Yup. Remember
-our discussion about `parse()`? If we give a non-number answer, we’ll `panic!`
-and quit. Observe:
-
-```bash
-$ cargo run
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.58 secs
-     Running `target/guessing_game`
-Guess the number!
-The secret number is: 59
-Please input your guess.
-45
-You guessed: 45
-Too small!
-Please input your guess.
-60
-You guessed: 60
-Too big!
-Please input your guess.
-59
-You guessed: 59
-You win!
-Please input your guess.
-quit
-thread 'main' panicked at 'Please type a number!'
-```
-
-Ha! `quit` actually quits. As does any other non-number input. Well, this is
-suboptimal to say the least. First, let’s actually quit when you win the game:
-
-```rust,ignore
-extern crate rand;
-
-use std::io;
-use std::cmp::Ordering;
-use rand::Rng;
-
-fn main() {
-    println!("Guess the number!");
-
-    let secret_number = rand::thread_rng().gen_range(1, 101);
-
-    println!("The secret number is: {}", secret_number);
-
-    loop {
-        println!("Please input your guess.");
-
-        let mut guess = String::new();
-
-        io::stdin().read_line(&mut guess)
-            .expect("Failed to read line");
-
-        let guess: u32 = guess.trim().parse()
-            .expect("Please type a number!");
-
-        println!("You guessed: {}", guess);
-
-        match guess.cmp(&secret_number) {
-            Ordering::Less    => println!("Too small!"),
-            Ordering::Greater => println!("Too big!"),
-            Ordering::Equal   => {
-                println!("You win!");
-                break;
-            }
-        }
-    }
-}
-```
-
-By adding the `break` line after the `You win!`, we’ll exit the loop when we
-win. Exiting the loop also means exiting the program, since it’s the last
-thing in `main()`. We have only one more tweak to make: when someone inputs a
-non-number, we don’t want to quit, we want to ignore it. We can do that
-like this:
-
-```rust,ignore
-extern crate rand;
-
-use std::io;
-use std::cmp::Ordering;
-use rand::Rng;
-
-fn main() {
-    println!("Guess the number!");
-
-    let secret_number = rand::thread_rng().gen_range(1, 101);
-
-    println!("The secret number is: {}", secret_number);
-
-    loop {
-        println!("Please input your guess.");
-
-        let mut guess = String::new();
-
-        io::stdin().read_line(&mut guess)
-            .expect("Failed to read line");
-
-        let guess: u32 = match guess.trim().parse() {
-            Ok(num) => num,
-            Err(_) => continue,
-        };
-
-        println!("You guessed: {}", guess);
-
-        match guess.cmp(&secret_number) {
-            Ordering::Less    => println!("Too small!"),
-            Ordering::Greater => println!("Too big!"),
-            Ordering::Equal   => {
-                println!("You win!");
-                break;
-            }
-        }
-    }
-}
-```
-
-These are the lines that changed:
-
-```rust,ignore
-let guess: u32 = match guess.trim().parse() {
-    Ok(num) => num,
-    Err(_) => continue,
-};
-```
-This is how you generally move from ‘crash on error’ to ‘actually handle the
-error’, by switching from `expect()` to a `match` statement. A `Result` is
-returned by `parse()`, this is an `enum`  like `Ordering`, but in this case,
-each variant has some data associated with it: `Ok` is a success, and `Err` is a
-failure. Each contains more information: the successfully parsed integer, or an
-error type. In this case, we `match` on `Ok(num)`, which sets the name `num` to
-the unwrapped `Ok` value (the integer), and then we  return it on the
-right-hand side. In the `Err` case, we don’t care what kind of error it is, so
-we just use the catch all `_` instead of a name. This catches everything that
-isn't `Ok`, and `continue` lets us move to the next iteration of the loop; in
-effect, this enables us to ignore all errors and continue with our program.
-
-Now we should be good! Let’s try:
-
-```bash
-$ cargo run
-   Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.57 secs
-     Running `target/guessing_game`
-Guess the number!
-The secret number is: 61
-Please input your guess.
-10
-You guessed: 10
-Too small!
-Please input your guess.
-99
-You guessed: 99
-Too big!
-Please input your guess.
-foo
-Please input your guess.
-61
-You guessed: 61
-You win!
-```
-
-Awesome! With one tiny last tweak, we have finished the guessing game. Can you
-think of what it is? That’s right, we don’t want to print out the secret
-number. It was good for testing, but it kind of ruins the game. Here’s our
-final source:
-
-```rust,ignore
-extern crate rand;
-
-use std::io;
-use std::cmp::Ordering;
-use rand::Rng;
-
-fn main() {
-    println!("Guess the number!");
-
-    let secret_number = rand::thread_rng().gen_range(1, 101);
-
-    loop {
-        println!("Please input your guess.");
-
-        let mut guess = String::new();
-
-        io::stdin().read_line(&mut guess)
-            .expect("Failed to read line");
-
-        let guess: u32 = match guess.trim().parse() {
-            Ok(num) => num,
-            Err(_) => continue,
-        };
-
-        println!("You guessed: {}", guess);
-
-        match guess.cmp(&secret_number) {
-            Ordering::Less    => println!("Too small!"),
-            Ordering::Greater => println!("Too big!"),
-            Ordering::Equal   => {
-                println!("You win!");
-                break;
-            }
-        }
-    }
-}
-```
-
-# Complete!
-
-This project showed you a lot: `let`, `match`, methods, associated
-functions, using external crates, and more.
-
-At this point, you have successfully built the Guessing Game! Congratulations!
diff --git a/src/doc/book/src/if-let.md b/src/doc/book/src/if-let.md
deleted file mode 100644 (file)
index 9eeac3d..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-# if let
-
-`if let` permits [patterns][patterns] matching within the condition of an [if][if] statement.
-This allows us to reduce the overhead of certain kinds of [pattern][patterns] matches
-and express them in a more convenient way.  
-
-For example, let’s say we have some sort of `Option<T>`. We want to call a function
-on it if it’s `Some<T>`, but do nothing if it’s `None`. That looks like this:
-
-```rust
-# let option = Some(5);
-# fn foo(x: i32) { }
-match option {
-    Some(x) => { foo(x) },
-    None => {},
-}
-```
-
-We don’t have to use `match` here, for example, we could use `if`:
-
-```rust
-# let option = Some(5);
-# fn foo(x: i32) { }
-if option.is_some() {
-    let x = option.unwrap();
-    foo(x);
-}
-```
-
-Neither of these options is particularly appealing. We can use `if let` to
-do the same thing in a nicer way:
-
-```rust
-# let option = Some(5);
-# fn foo(x: i32) { }
-if let Some(x) = option {
-    foo(x);
-}
-```
-
-If a [pattern][patterns] matches successfully, it binds any appropriate parts of
-the value to the identifiers in the pattern, then evaluates the expression. If
-the pattern doesn’t match, nothing happens.
-
-If you want to do something else when the pattern does not match, you can
-use `else`:
-
-```rust
-# let option = Some(5);
-# fn foo(x: i32) { }
-# fn bar() { }
-if let Some(x) = option {
-    foo(x);
-} else {
-    bar();
-}
-```
-
-## `while let`
-
-In a similar fashion, `while let` can be used when you want to conditionally
-loop  as long as a value matches a certain pattern. It turns code like this:
-
-```rust
-let mut v = vec![1, 3, 5, 7, 11];
-loop {
-    match v.pop() {
-        Some(x) =>  println!("{}", x),
-        None => break,
-    }
-}
-```
-
-Into code like this:
-
-```rust
-let mut v = vec![1, 3, 5, 7, 11];
-while let Some(x) = v.pop() {
-    println!("{}", x);
-}
-```
-
-[patterns]: patterns.html
-[if]: if.html
diff --git a/src/doc/book/src/if.md b/src/doc/book/src/if.md
deleted file mode 100644 (file)
index d745037..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-# if
-
-Rust’s take on `if` is not particularly complex, but it’s much more like the
-`if` you’ll find in a dynamically typed language than in a more traditional
-systems language. So let’s talk about it, to make sure you grasp the nuances.
-
-`if` is a specific form of a more general concept, the ‘branch’, whose name comes
-from a branch in a tree: a decision point, where depending on a choice,
-multiple paths can be taken.
-
-In the case of `if`, there is one choice that leads down two paths:
-
-```rust
-let x = 5;
-
-if x == 5 {
-    println!("x is five!");
-}
-```
-
-If we changed the value of `x` to something else, this line would not print.
-More specifically, if the expression after the `if` evaluates to `true`, then
-the block is executed. If it’s `false`, then it is not.
-
-If you want something to happen in the `false` case, use an `else`:
-
-```rust
-let x = 5;
-
-if x == 5 {
-    println!("x is five!");
-} else {
-    println!("x is not five :(");
-}
-```
-
-If there is more than one case, use an `else if`:
-
-```rust
-let x = 5;
-
-if x == 5 {
-    println!("x is five!");
-} else if x == 6 {
-    println!("x is six!");
-} else {
-    println!("x is not five or six :(");
-}
-```
-
-This is all pretty standard. However, you can also do this:
-
-```rust
-let x = 5;
-
-let y = if x == 5 {
-    10
-} else {
-    15
-}; // y: i32
-```
-
-Which we can (and probably should) write like this:
-
-```rust
-let x = 5;
-
-let y = if x == 5 { 10 } else { 15 }; // y: i32
-```
-
-This works because `if` is an expression. The value of the expression is the
-value of the last expression in whichever branch was chosen. An `if` without an
-`else` always results in `()` as the value.
diff --git a/src/doc/book/src/iterators.md b/src/doc/book/src/iterators.md
deleted file mode 100644 (file)
index 8ee6c08..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-# Iterators
-
-Let's talk about loops.
-
-Remember Rust's `for` loop? Here's an example:
-
-```rust
-for x in 0..10 {
-    println!("{}", x);
-}
-```
-
-Now that you know more Rust, we can talk in detail about how this works.
-Ranges (the `0..10`) are 'iterators'. An iterator is something that we can
-call the `.next()` method on repeatedly, and it gives us a sequence of things.
-
-(By the way, a range with two dots like `0..10` is inclusive on the left (so it
-starts at 0) and exclusive on the right (so it ends at 9). A mathematician
-would write "[0, 10)". To get a range that goes all the way up to 10 you can
-write `0...10`.)
-
-Like this:
-
-```rust
-let mut range = 0..10;
-
-loop {
-    match range.next() {
-        Some(x) => {
-            println!("{}", x);
-        },
-        None => { break }
-    }
-}
-```
-
-We make a mutable binding to the range, which is our iterator. We then `loop`,
-with an inner `match`. This `match` is used on the result of `range.next()`,
-which gives us a reference to the next value of the iterator. `next` returns an
-`Option<i32>`, in this case, which will be `Some(i32)` when we have a value and
-`None` once we run out. If we get `Some(i32)`, we print it out, and if we get
-`None`, we `break` out of the loop.
-
-This code sample is basically the same as our `for` loop version. The `for`
-loop is a handy way to write this `loop`/`match`/`break` construct.
-
-`for` loops aren't the only thing that uses iterators, however. Writing your
-own iterator involves implementing the `Iterator` trait. While doing that is
-outside of the scope of this guide, Rust provides a number of useful iterators
-to accomplish various tasks. But first, a few notes about limitations of ranges.
-
-Ranges are very primitive, and we often can use better alternatives. Consider the
-following Rust anti-pattern: using ranges to emulate a C-style `for` loop. Let’s
-suppose you needed to iterate over the contents of a vector. You may be tempted
-to write this:
-
-```rust
-let nums = vec![1, 2, 3];
-
-for i in 0..nums.len() {
-    println!("{}", nums[i]);
-}
-```
-
-This is strictly worse than using an actual iterator. You can iterate over vectors
-directly, so write this:
-
-```rust
-let nums = vec![1, 2, 3];
-
-for num in &nums {
-    println!("{}", num);
-}
-```
-
-There are two reasons for this. First, this more directly expresses what we
-mean. We iterate through the entire vector, rather than iterating through
-indexes, and then indexing the vector. Second, this version is more efficient:
-the first version will have extra bounds checking because it used indexing,
-`nums[i]`. But since we yield a reference to each element of the vector in turn
-with the iterator, there's no bounds checking in the second example. This is
-very common with iterators: we can ignore unnecessary bounds checks, but still
-know that we're safe.
-
-There's another detail here that's not 100% clear because of how `println!`
-works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`,
-not an `i32` itself. `println!` handles the dereferencing for us, so we don't
-see it. This code works fine too:
-
-```rust
-let nums = vec![1, 2, 3];
-
-for num in &nums {
-    println!("{}", *num);
-}
-```
-
-Now we're explicitly dereferencing `num`. Why does `&nums` give us
-references?  Firstly, because we explicitly asked it to with
-`&`. Secondly, if it gave us the data itself, we would have to be its
-owner, which would involve making a copy of the data and giving us the
-copy. With references, we're only borrowing a reference to the data,
-and so it's only passing a reference, without needing to do the move.
-
-So, now that we've established that ranges are often not what you want, let's
-talk about what you do want instead.
-
-There are three broad classes of things that are relevant here: iterators,
-*iterator adaptors*, and *consumers*. Here's some definitions:
-
-* *iterators* give you a sequence of values.
-* *iterator adaptors* operate on an iterator, producing a new iterator with a
-  different output sequence.
-* *consumers* operate on an iterator, producing some final set of values.
-
-Let's talk about consumers first, since you've already seen an iterator, ranges.
-
-## Consumers
-
-A *consumer* operates on an iterator, returning some kind of value or values.
-The most common consumer is `collect()`. This code doesn't quite compile,
-but it shows the intention:
-
-```rust,ignore
-let one_to_one_hundred = (1..101).collect();
-```
-
-As you can see, we call `collect()` on our iterator. `collect()` takes
-as many values as the iterator will give it, and returns a collection
-of the results. So why won't this compile? Rust can't determine what
-type of things you want to collect, and so you need to let it know.
-Here's the version that does compile:
-
-```rust
-let one_to_one_hundred = (1..101).collect::<Vec<i32>>();
-```
-
-If you remember, the [`::<>` syntax](generics.html#resolving-ambiguities)
-allows us to give a type hint that tells the compiler we want a vector of
-integers. You don't always need to use the whole type, though. Using a `_`
-will let you provide a partial hint:
-
-```rust
-let one_to_one_hundred = (1..101).collect::<Vec<_>>();
-```
-
-This says "Collect into a `Vec<T>`, please, but infer what the `T` is for me."
-`_` is sometimes called a "type placeholder" for this reason.
-
-`collect()` is the most common consumer, but there are others too. `find()`
-is one:
-
-```rust
-let greater_than_forty_two = (0..100)
-                             .find(|x| *x > 42);
-
-match greater_than_forty_two {
-    Some(_) => println!("Found a match!"),
-    None => println!("No match found :("),
-}
-```
-
-`find` takes a closure, and works on a reference to each element of an
-iterator. This closure returns `true` if the element is the element we're
-looking for, and `false` otherwise. `find` returns the first element satisfying
-the specified predicate. Because we might not find a matching element, `find`
-returns an `Option` rather than the element itself.
-
-Another important consumer is `fold`. Here's what it looks like:
-
-```rust
-let sum = (1..4).fold(0, |sum, x| sum + x);
-```
-
-`fold()` is a consumer that looks like this:
-`fold(base, |accumulator, element| ...)`. It takes two arguments: the first
-is an element called the *base*. The second is a closure that itself takes two
-arguments: the first is called the *accumulator*, and the second is an
-*element*. Upon each iteration, the closure is called, and the result is the
-value of the accumulator on the next iteration. On the first iteration, the
-base is the value of the accumulator.
-
-Okay, that's a bit confusing. Let's examine the values of all of these things
-in this iterator:
-
-| base | accumulator | element | closure result |
-|------|-------------|---------|----------------|
-| 0    | 0           | 1       | 1              |
-| 0    | 1           | 2       | 3              |
-| 0    | 3           | 3       | 6              |
-
-We called `fold()` with these arguments:
-
-```rust
-# (1..4)
-.fold(0, |sum, x| sum + x);
-```
-
-So, `0` is our base, `sum` is our accumulator, and `x` is our element.  On the
-first iteration, we set `sum` to `0`, and `x` is the first element of `nums`,
-`1`. We then add `sum` and `x`, which gives us `0 + 1 = 1`. On the second
-iteration, that value becomes our accumulator, `sum`, and the element is
-the second element of the array, `2`. `1 + 2 = 3`, and so that becomes
-the value of the accumulator for the last iteration. On that iteration,
-`x` is the last element, `3`, and `3 + 3 = 6`, which is our final
-result for our sum. `1 + 2 + 3 = 6`, and that's the result we got.
-
-Whew. `fold` can be a bit strange the first few times you see it, but once it
-clicks, you can use it all over the place. Any time you have a list of things,
-and you want a single result, `fold` is appropriate.
-
-Consumers are important due to one additional property of iterators we haven't
-talked about yet: laziness. Let's talk some more about iterators, and you'll
-see why consumers matter.
-
-## Iterators
-
-As we've said before, an iterator is something that we can call the
-`.next()` method on repeatedly, and it gives us a sequence of things.
-Because you need to call the method, this means that iterators
-can be *lazy* and not generate all of the values upfront. This code,
-for example, does not actually generate the numbers `1-99`, instead
-creating a value that merely represents the sequence:
-
-```rust
-let nums = 1..100;
-```
-
-Since we didn't do anything with the range, it didn't generate the sequence.
-Let's add the consumer:
-
-```rust
-let nums = (1..100).collect::<Vec<i32>>();
-```
-
-Now, `collect()` will require that the range gives it some numbers, and so
-it will do the work of generating the sequence.
-
-Ranges are one of two basic iterators that you'll see. The other is `iter()`.
-`iter()` can turn a vector into a simple iterator that gives you each element
-in turn:
-
-```rust
-let nums = vec![1, 2, 3];
-
-for num in nums.iter() {
-   println!("{}", num);
-}
-```
-
-These two basic iterators should serve you well. There are some more
-advanced iterators, including ones that are infinite.
-
-That's enough about iterators. Iterator adaptors are the last concept
-we need to talk about with regards to iterators. Let's get to it!
-
-## Iterator adaptors
-
-*Iterator adaptors* take an iterator and modify it somehow, producing
-a new iterator. The simplest one is called `map`:
-
-```rust,ignore
-(1..100).map(|x| x + 1);
-```
-
-`map` is called upon another iterator, and produces a new iterator where each
-element reference has the closure it's been given as an argument called on it.
-So this would give us the numbers from `2-100`. Well, almost! If you
-compile the example, you'll get a warning:
-
-```text
-warning: unused result which must be used: iterator adaptors are lazy and
-         do nothing unless consumed, #[warn(unused_must_use)] on by default
-(1..100).map(|x| x + 1);
- ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-```
-
-Laziness strikes again! That closure will never execute. This example
-doesn't print any numbers:
-
-```rust,ignore
-(1..100).map(|x| println!("{}", x));
-```
-
-If you are trying to execute a closure on an iterator for its side effects,
-use `for` instead.
-
-There are tons of interesting iterator adaptors. `take(n)` will return an
-iterator over the next `n` elements of the original iterator. Let's try it out
-with an infinite iterator:
-
-```rust
-for i in (1..).take(5) {
-    println!("{}", i);
-}
-```
-
-This will print
-
-```text
-1
-2
-3
-4
-5
-```
-
-`filter()` is an adapter that takes a closure as an argument. This closure
-returns `true` or `false`. The new iterator `filter()` produces
-only the elements that the closure returns `true` for:
-
-```rust
-for i in (1..100).filter(|&x| x % 2 == 0) {
-    println!("{}", i);
-}
-```
-
-This will print all of the even numbers between one and a hundred.
-(Note that, unlike `map`, the closure passed to `filter` is passed a reference
-to the element instead of the element itself. The filter predicate here uses
-the `&x` pattern to extract the integer. The filter closure is passed a
-reference because it returns `true` or `false` instead of the element,
-so the `filter` implementation must retain ownership to put the elements
-into the newly constructed iterator.)
-
-You can chain all three things together: start with an iterator, adapt it
-a few times, and then consume the result. Check it out:
-
-```rust
-(1..)
-    .filter(|&x| x % 2 == 0)
-    .filter(|&x| x % 3 == 0)
-    .take(5)
-    .collect::<Vec<i32>>();
-```
-
-This will give you a vector containing `6`, `12`, `18`, `24`, and `30`.
-
-This is just a small taste of what iterators, iterator adaptors, and consumers
-can help you with. There are a number of really useful iterators, and you can
-write your own as well. Iterators provide a safe, efficient way to manipulate
-all kinds of lists. They're a little unusual at first, but if you play with
-them, you'll get hooked. For a full list of the different iterators and
-consumers, check out the [iterator module documentation](../std/iter/index.html).
diff --git a/src/doc/book/src/lifetimes.md b/src/doc/book/src/lifetimes.md
deleted file mode 100644 (file)
index 042d9af..0000000
+++ /dev/null
@@ -1,428 +0,0 @@
-# Lifetimes
-
-This is the last of three sections presenting Rust’s ownership system. This is one of
-Rust’s most distinct and compelling features, with which Rust developers should
-become quite acquainted. Ownership is how Rust achieves its largest goal,
-memory safety. There are a few distinct concepts, each with its own chapter:
-
-* [ownership][ownership], the key concept
-* [borrowing][borrowing], and their associated feature ‘references’
-* lifetimes, which you’re reading now
-
-These three chapters are related, and in order. You’ll need all three to fully
-understand the ownership system.
-
-[ownership]: ownership.html
-[borrowing]: references-and-borrowing.html
-
-# Meta
-
-Before we get to the details, two important notes about the ownership system.
-
-Rust has a focus on safety and speed. It accomplishes these goals through many
-‘zero-cost abstractions’, which means that in Rust, abstractions cost as little
-as possible in order to make them work. The ownership system is a prime example
-of a zero-cost abstraction. All of the analysis we’ll talk about in this guide
-is _done at compile time_. You do not pay any run-time cost for any of these
-features.
-
-However, this system does have a certain cost: learning curve. Many new users
-to Rust experience something we like to call ‘fighting with the borrow
-checker’, where the Rust compiler refuses to compile a program that the author
-thinks is valid. This often happens because the programmer’s mental model of
-how ownership should work doesn’t match the actual rules that Rust implements.
-You probably will experience similar things at first. There is good news,
-however: more experienced Rust developers report that once they work with the
-rules of the ownership system for a period of time, they fight the borrow
-checker less and less.
-
-With that in mind, let’s learn about lifetimes.
-
-# Lifetimes
-
-Lending out a reference to a resource that someone else owns can be
-complicated. For example, imagine this set of operations:
-
-1. I acquire a handle to some kind of resource.
-2. I lend you a reference to the resource.
-3. I decide I’m done with the resource, and deallocate it, while you still have
-  your reference.
-4. You decide to use the resource.
-
-Uh oh! Your reference is pointing to an invalid resource. This is called a
-dangling pointer or ‘use after free’, when the resource is memory. A small
-example of such a situation would be:
-
-```rust,compile_fail
-let r;              // Introduce reference: `r`.
-{
-    let i = 1;      // Introduce scoped value: `i`.
-    r = &i;         // Store reference of `i` in `r`.
-}                   // `i` goes out of scope and is dropped.
-
-println!("{}", r);  // `r` still refers to `i`.
-```
-
-To fix this, we have to make sure that step four never happens after step
-three. In the small example above the Rust compiler is able to report the issue
-as it can see the lifetimes of the various values in the function.
-
-When we have a function that takes arguments by reference the situation becomes
-more complex. Consider the following example:
-
-```rust,compile_fail,E0106
-fn skip_prefix(line: &str, prefix: &str) -> &str {
-    // ...
-#   line
-}
-
-let line = "lang:en=Hello World!";
-let lang = "en";
-
-let v;
-{
-    let p = format!("lang:{}=", lang);  // -+ `p` comes into scope.
-    v = skip_prefix(line, p.as_str());  //  |
-}                                       // -+ `p` goes out of scope.
-println!("{}", v);
-```
-
-Here we have a function `skip_prefix` which takes two `&str` references
-as parameters and returns a single `&str` reference. We call it
-by passing in references to `line` and `p`: Two variables with different
-lifetimes. Now the safety of the `println!`-line depends on whether the
-reference returned by `skip_prefix` function references the still living
-`line` or the already dropped `p` string.
-
-Because of the above ambiguity, Rust will refuse to compile the example
-code. To get it to compile we need to tell the compiler more about the
-lifetimes of the references. This can be done by making the lifetimes
-explicit in the function declaration:
-
-```rust
-fn skip_prefix<'a, 'b>(line: &'a str, prefix: &'b str) -> &'a str {
-    // ...
-#   line
-}
-```
-
-Let's examine the changes without going too deep into the syntax for now -
-we'll get to that later. The first change was adding the `<'a, 'b>` after the
-method name. This introduces two lifetime parameters: `'a` and `'b`. Next, each
-reference in the function signature was associated with one of the lifetime
-parameters by adding the lifetime name after the `&`. This tells the compiler
-how the lifetimes between different references are related.
-
-As a result the compiler is now able to deduce that the return value of
-`skip_prefix` has the same lifetime as the `line` parameter, which makes the `v`
-reference safe to use even after the `p` goes out of scope in the original
-example.
-
-In addition to the compiler being able to validate the usage of `skip_prefix`
-return value, it can also ensure that the implementation follows the contract
-established by the function declaration. This is useful especially when you are
-implementing traits that are introduced [later in the book][traits].
-
-**Note** It's important to understand that lifetime annotations are
-_descriptive_, not _prescriptive_. This means that how long a reference is valid
-is determined by the code, not by the annotations. The annotations, however,
-give information about lifetimes to the compiler that uses them to check the
-validity of references. The compiler can do so without annotations in simple
-cases, but needs the programmer's support in complex scenarios.
-
-[traits]: traits.html
-
-# Syntax
-
-The `'a` reads ‘the lifetime a’. Technically, every reference has some lifetime
-associated with it, but the compiler lets you elide (i.e. omit, see
-["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we
-get to that, though, let’s look at a short example with explicit lifetimes:
-
-[lifetime-elision]: #lifetime-elision
-
-```rust,ignore
-fn bar<'a>(...)
-```
-
-We previously talked a little about [function syntax][functions], but we didn’t
-discuss the `<>`s after a function’s name. A function can have ‘generic
-parameters’ between the `<>`s, of which lifetimes are one kind. We’ll discuss
-other kinds of generics [later in the book][generics], but for now, let’s
-focus on the lifetimes aspect.
-
-[functions]: functions.html
-[generics]: generics.html
-
-We use `<>` to declare our lifetimes. This says that `bar` has one lifetime,
-`'a`. If we had two reference parameters with different lifetimes, it would
-look like this:
-
-
-```rust,ignore
-fn bar<'a, 'b>(...)
-```
-
-Then in our parameter list, we use the lifetimes we’ve named:
-
-```rust,ignore
-...(x: &'a i32)
-```
-
-If we wanted a `&mut` reference, we’d do this:
-
-```rust,ignore
-...(x: &'a mut i32)
-```
-
-If you compare `&mut i32` to `&'a mut i32`, they’re the same, it’s that
-the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut
-i32` as ‘a mutable reference to an `i32`’ and `&'a mut i32` as ‘a mutable
-reference to an `i32` with the lifetime `'a`’.
-
-# In `struct`s
-
-You’ll also need explicit lifetimes when working with [`struct`][structs]s that
-contain references:
-
-```rust
-struct Foo<'a> {
-    x: &'a i32,
-}
-
-fn main() {
-    let y = &5; // This is the same as `let _y = 5; let y = &_y;`.
-    let f = Foo { x: y };
-
-    println!("{}", f.x);
-}
-```
-
-[structs]: structs.html
-
-As you can see, `struct`s can also have lifetimes. In a similar way to functions,
-
-```rust
-struct Foo<'a> {
-# x: &'a i32,
-# }
-```
-
-declares a lifetime, and
-
-```rust
-# struct Foo<'a> {
-x: &'a i32,
-# }
-```
-
-uses it. So why do we need a lifetime here? We need to ensure that any reference
-to a `Foo` cannot outlive the reference to an `i32` it contains.
-
-## `impl` blocks
-
-Let’s implement a method on `Foo`:
-
-```rust
-struct Foo<'a> {
-    x: &'a i32,
-}
-
-impl<'a> Foo<'a> {
-    fn x(&self) -> &'a i32 { self.x }
-}
-
-fn main() {
-    let y = &5; // This is the same as `let _y = 5; let y = &_y;`.
-    let f = Foo { x: y };
-
-    println!("x is: {}", f.x());
-}
-```
-
-As you can see, we need to declare a lifetime for `Foo` in the `impl` line. We repeat
-`'a` twice, like on functions: `impl<'a>` defines a lifetime `'a`, and `Foo<'a>`
-uses it.
-
-## Multiple lifetimes
-
-If you have multiple references, you can use the same lifetime multiple times:
-
-```rust
-fn x_or_y<'a>(x: &'a str, y: &'a str) -> &'a str {
-#    x
-# }
-```
-
-This says that `x` and `y` both are alive for the same scope, and that the
-return value is also alive for that scope. If you wanted `x` and `y` to have
-different lifetimes, you can use multiple lifetime parameters:
-
-```rust
-fn x_or_y<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
-#    x
-# }
-```
-
-In this example, `x` and `y` have different valid scopes, but the return value
-has the same lifetime as `x`.
-
-## Thinking in scopes
-
-A way to think about lifetimes is to visualize the scope that a reference is
-valid for. For example:
-
-```rust
-fn main() {
-    let y = &5;     // -+ `y` comes into scope.
-                    //  |
-    // Stuff...     //  |
-                    //  |
-}                   // -+ `y` goes out of scope.
-```
-
-Adding in our `Foo`:
-
-```rust
-struct Foo<'a> {
-    x: &'a i32,
-}
-
-fn main() {
-    let y = &5;           // -+ `y` comes into scope.
-    let f = Foo { x: y }; // -+ `f` comes into scope.
-                          //  |
-    // Stuff...           //  |
-                          //  |
-}                         // -+ `f` and `y` go out of scope.
-```
-
-Our `f` lives within the scope of `y`, so everything works. What if it didn’t?
-This code won’t work:
-
-```rust,ignore
-struct Foo<'a> {
-    x: &'a i32,
-}
-
-fn main() {
-    let x;                    // -+ `x` comes into scope.
-                              //  |
-    {                         //  |
-        let y = &5;           // ---+ `y` comes into scope.
-        let f = Foo { x: y }; // ---+ `f` comes into scope.
-        x = &f.x;             //  | | This causes an error.
-    }                         // ---+ `f` and y go out of scope.
-                              //  |
-    println!("{}", x);        //  |
-}                             // -+ `x` goes out of scope.
-```
-
-Whew! As you can see here, the scopes of `f` and `y` are smaller than the scope
-of `x`. But when we do `x = &f.x`, we make `x` a reference to something that’s
-about to go out of scope.
-
-Named lifetimes are a way of giving these scopes a name. Giving something a
-name is the first step towards being able to talk about it.
-
-## 'static
-
-The lifetime named ‘static’ is a special lifetime. It signals that something
-has the lifetime of the entire program. Most Rust programmers first come across
-`'static` when dealing with strings:
-
-```rust
-let x: &'static str = "Hello, world.";
-```
-
-String literals have the type `&'static str` because the reference is always
-alive: they are baked into the data segment of the final binary. Another
-example are globals:
-
-```rust
-static FOO: i32 = 5;
-let x: &'static i32 = &FOO;
-```
-
-This adds an `i32` to the data segment of the binary, and `x` is a reference
-to it.
-
-## Lifetime Elision
-
-Rust supports powerful local type inference in the bodies of functions, but it
-deliberately does not perform any reasoning about types for item signatures. 
-However, for ergonomic reasons, a very restricted secondary inference algorithm called 
-“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring 
-lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision 
-acts as a shorthand for writing an item signature, while not hiding
-away the actual types involved as full local inference would if applied to it.
-
-When talking about lifetime elision, we use the terms *input lifetime* and
-*output lifetime*. An *input lifetime* is a lifetime associated with a parameter
-of a function, and an *output lifetime* is a lifetime associated with the return
-value of a function. For example, this function has an input lifetime:
-
-```rust,ignore
-fn foo<'a>(bar: &'a str)
-```
-
-This one has an output lifetime:
-
-```rust,ignore
-fn foo<'a>() -> &'a str
-```
-
-This one has a lifetime in both positions:
-
-```rust,ignore
-fn foo<'a>(bar: &'a str) -> &'a str
-```
-
-Here are the three rules:
-
-* Each elided lifetime in a function’s arguments becomes a distinct lifetime
-  parameter.
-
-* If there is exactly one input lifetime, elided or not, that lifetime is
-  assigned to all elided lifetimes in the return values of that function.
-
-* If there are multiple input lifetimes, but one of them is `&self` or `&mut
-  self`, the lifetime of `self` is assigned to all elided output lifetimes.
-
-Otherwise, it is an error to elide an output lifetime.
-
-### Examples
-
-Here are some examples of functions with elided lifetimes.  We’ve paired each
-example of an elided lifetime with its expanded form.
-
-```rust,ignore
-fn print(s: &str); // elided
-fn print<'a>(s: &'a str); // expanded
-
-fn debug(lvl: u32, s: &str); // elided
-fn debug<'a>(lvl: u32, s: &'a str); // expanded
-```
-
-In the preceding example, `lvl` doesn’t need a lifetime because it’s not a
-reference (`&`). Only things relating to references (such as a `struct`
-which contains a reference) need lifetimes.
-
-```rust,ignore
-fn substr(s: &str, until: u32) -> &str; // elided
-fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded
-
-fn get_str() -> &str; // ILLEGAL, no inputs
-
-fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
-fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is ambiguous
-
-fn get_mut(&mut self) -> &mut T; // elided
-fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
-
-fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
-fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
-
-fn new(buf: &mut [u8]) -> BufWriter; // elided
-fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
-```
diff --git a/src/doc/book/src/loops.md b/src/doc/book/src/loops.md
deleted file mode 100644 (file)
index b7658d5..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-# Loops
-
-Rust currently provides three approaches to performing some kind of iterative activity. They are: `loop`, `while` and `for`. Each approach has its own set of uses.
-
-## loop
-
-The infinite `loop` is the simplest form of loop available in Rust. Using the keyword `loop`, Rust provides a way to loop indefinitely until some terminating statement is reached. Rust's infinite `loop`s look like this:
-
-```rust,ignore
-loop {
-    println!("Loop forever!");
-}
-```
-
-## while
-
-Rust also has a `while` loop. It looks like this:
-
-```rust
-let mut x = 5; // mut x: i32
-let mut done = false; // mut done: bool
-
-while !done {
-    x += x - 3;
-
-    println!("{}", x);
-
-    if x % 5 == 0 {
-        done = true;
-    }
-}
-```
-
-`while` loops are the correct choice when you’re not sure how many times
-you need to loop.
-
-If you need an infinite loop, you may be tempted to write this:
-
-```rust,ignore
-while true {
-```
-
-However, `loop` is far better suited to handle this case:
-
-```rust,ignore
-loop {
-```
-
-Rust’s control-flow analysis treats this construct differently than a `while
-true`, since we know that it will always loop. In general, the more information
-we can give to the compiler, the better it can do with safety and code
-generation, so you should always prefer `loop` when you plan to loop
-infinitely.
-
-## for
-
-The `for` loop is used to loop a particular number of times. Rust’s `for` loops
-work a bit differently than in other systems languages, however. Rust’s `for`
-loop doesn’t look like this “C-style” `for` loop:
-
-```c
-for (x = 0; x < 10; x++) {
-    printf( "%d\n", x );
-}
-```
-
-Instead, it looks like this:
-
-```rust
-for x in 0..10 {
-    println!("{}", x); // x: i32
-}
-```
-
-In slightly more abstract terms,
-
-```rust,ignore
-for var in expression {
-    code
-}
-```
-
-The expression is an item that can be converted into an [iterator] using
-[`IntoIterator`]. The iterator gives back a series of elements. Each element is
-one iteration of the loop. That value is then bound to the name `var`, which is
-valid for the loop body. Once the body is over, the next value is fetched from
-the iterator, and we loop another time. When there are no more values, the `for`
-loop is over.
-
-[iterator]: iterators.html
-[`IntoIterator`]: ../std/iter/trait.IntoIterator.html
-
-In our example, `0..10` is an expression that takes a start and an end position,
-and gives an iterator over those values. The upper bound is exclusive, though,
-so our loop will print `0` through `9`, not `10`.
-
-Rust does not have the “C-style” `for` loop on purpose. Manually controlling
-each element of the loop is complicated and error prone, even for experienced C
-developers.
-
-### Enumerate
-
-When you need to keep track of how many times you have already looped, you can
-use the `.enumerate()` function.
-
-#### On ranges:
-
-```rust
-for (index, value) in (5..10).enumerate() {
-    println!("index = {} and value = {}", index, value);
-}
-```
-
-Outputs:
-
-```text
-index = 0 and value = 5
-index = 1 and value = 6
-index = 2 and value = 7
-index = 3 and value = 8
-index = 4 and value = 9
-```
-
-Don't forget to add the parentheses around the range.
-
-#### On iterators:
-
-```rust
-let lines = "hello\nworld".lines();
-
-for (linenumber, line) in lines.enumerate() {
-    println!("{}: {}", linenumber, line);
-}
-```
-
-Outputs:
-
-```text
-0: hello
-1: world
-```
-
-## Ending iteration early
-
-Let’s take a look at that `while` loop we had earlier:
-
-```rust
-let mut x = 5;
-let mut done = false;
-
-while !done {
-    x += x - 3;
-
-    println!("{}", x);
-
-    if x % 5 == 0 {
-        done = true;
-    }
-}
-```
-
-We had to keep a dedicated `mut` boolean variable binding, `done`, to know
-when we should exit out of the loop. Rust has two keywords to help us with
-modifying iteration: `break` and `continue`.
-
-In this case, we can write the loop in a better way with `break`:
-
-```rust
-let mut x = 5;
-
-loop {
-    x += x - 3;
-
-    println!("{}", x);
-
-    if x % 5 == 0 { break; }
-}
-```
-
-We now loop forever with `loop` and use `break` to break out early. Issuing an explicit `return` statement will also serve to terminate the loop early.
-
-`continue` is similar, but instead of ending the loop, it goes to the next
-iteration. This will only print the odd numbers:
-
-```rust
-for x in 0..10 {
-    if x % 2 == 0 { continue; }
-
-    println!("{}", x);
-}
-```
-
-## Loop labels
-
-You may also encounter situations where you have nested loops and need to
-specify which one your `break` or `continue` statement is for. Like most
-other languages, by default a `break` or `continue` will apply to innermost
-loop. In a situation where you would like to `break` or `continue` for one
-of the outer loops, you can use labels to specify which loop the `break` or
- `continue` statement applies to. This will only print when both `x` and `y` are
- odd:
-
-```rust
-'outer: for x in 0..10 {
-    'inner: for y in 0..10 {
-        if x % 2 == 0 { continue 'outer; } // Continues the loop over `x`.
-        if y % 2 == 0 { continue 'inner; } // Continues the loop over `y`.
-        println!("x: {}, y: {}", x, y);
-    }
-}
-```
diff --git a/src/doc/book/src/macros.md b/src/doc/book/src/macros.md
deleted file mode 100644 (file)
index fa8e897..0000000
+++ /dev/null
@@ -1,763 +0,0 @@
-# Macros
-
-By now you’ve learned about many of the tools Rust provides for abstracting and
-reusing code. These units of code reuse have a rich semantic structure. For
-example, functions have a type signature, type parameters have trait bounds,
-and overloaded functions must belong to a particular trait.
-
-This structure means that Rust’s core abstractions have powerful compile-time
-correctness checking. But this comes at the price of reduced flexibility. If
-you visually identify a pattern of repeated code, you may find it’s difficult
-or cumbersome to express that pattern as a generic function, a trait, or
-anything else within Rust’s semantics.
-
-Macros allow us to abstract at a syntactic level. A macro invocation is
-shorthand for an "expanded" syntactic form. This expansion happens early in
-compilation, before any static checking. As a result, macros can capture many
-patterns of code reuse that Rust’s core abstractions cannot.
-
-The drawback is that macro-based code can be harder to understand, because
-fewer of the built-in rules apply. Like an ordinary function, a well-behaved
-macro can be used without understanding its implementation. However, it can be
-difficult to design a well-behaved macro!  Additionally, compiler errors in
-macro code are harder to interpret, because they describe problems in the
-expanded code, not the source-level form that developers use.
-
-These drawbacks make macros something of a "feature of last resort". That’s not
-to say that macros are bad; they are part of Rust because sometimes they’re
-needed for truly concise, well-abstracted code. Just keep this tradeoff in
-mind.
-
-# Defining a macro
-
-You may have seen the `vec!` macro, used to initialize a [vector][vector] with
-any number of elements.
-
-[vector]: vectors.html
-
-```rust
-let x: Vec<u32> = vec![1, 2, 3];
-# assert_eq!(x, [1, 2, 3]);
-```
-
-This can’t be an ordinary function, because it takes any number of arguments.
-But we can imagine it as syntactic shorthand for
-
-```rust
-let x: Vec<u32> = {
-    let mut temp_vec = Vec::new();
-    temp_vec.push(1);
-    temp_vec.push(2);
-    temp_vec.push(3);
-    temp_vec
-};
-# assert_eq!(x, [1, 2, 3]);
-```
-
-We can implement this shorthand, using a macro: [^actual]
-
-[^actual]: The actual definition of `vec!` in libcollections differs from the
-           one presented here, for reasons of efficiency and reusability.
-
-```rust
-macro_rules! vec {
-    ( $( $x:expr ),* ) => {
-        {
-            let mut temp_vec = Vec::new();
-            $(
-                temp_vec.push($x);
-            )*
-            temp_vec
-        }
-    };
-}
-# fn main() {
-#     assert_eq!(vec![1,2,3], [1, 2, 3]);
-# }
-```
-
-Whoa, that’s a lot of new syntax! Let’s break it down.
-
-```rust,ignore
-macro_rules! vec { ... }
-```
-
-This says we’re defining a macro named `vec`, much as `fn vec` would define a
-function named `vec`. In prose, we informally write a macro’s name with an
-exclamation point, e.g. `vec!`. The exclamation point is part of the invocation
-syntax and serves to distinguish a macro from an ordinary function.
-
-## Matching
-
-The macro is defined through a series of rules, which are pattern-matching
-cases. Above, we had
-
-```rust,ignore
-( $( $x:expr ),* ) => { ... };
-```
-
-This is like a `match` expression arm, but the matching happens on Rust syntax
-trees, at compile time. The semicolon is optional on the last (here, only)
-case. The "pattern" on the left-hand side of `=>` is known as a ‘matcher’.
-These have [their own little grammar] within the language.
-
-[their own little grammar]: ../reference/macros.html
-
-The matcher `$x:expr` will match any Rust expression, binding that syntax tree
-to the ‘metavariable’ `$x`. The identifier `expr` is a ‘fragment specifier’;
-the full possibilities are enumerated later in this chapter.
-Surrounding the matcher with `$(...),*` will match zero or more expressions,
-separated by commas.
-
-Aside from the special matcher syntax, any Rust tokens that appear in a matcher
-must match exactly. For example,
-
-```rust,ignore
-macro_rules! foo {
-    (x => $e:expr) => (println!("mode X: {}", $e));
-    (y => $e:expr) => (println!("mode Y: {}", $e));
-}
-
-fn main() {
-    foo!(y => 3);
-}
-```
-
-will print
-
-```text
-mode Y: 3
-```
-
-With
-
-```rust,ignore
-foo!(z => 3);
-```
-
-we get the compiler error
-
-```text
-error: no rules expected the token `z`
-```
-
-## Expansion
-
-The right-hand side of a macro rule is ordinary Rust syntax, for the most part.
-But we can splice in bits of syntax captured by the matcher. From the original
-example:
-
-```rust,ignore
-$(
-    temp_vec.push($x);
-)*
-```
-
-Each matched expression `$x` will produce a single `push` statement in the
-macro expansion. The repetition in the expansion proceeds in "lockstep" with
-repetition in the matcher (more on this in a moment).
-
-Because `$x` was already declared as matching an expression, we don’t repeat
-`:expr` on the right-hand side. Also, we don’t include a separating comma as
-part of the repetition operator. Instead, we have a terminating semicolon
-within the repeated block.
-
-Another detail: the `vec!` macro has *two* pairs of braces on the right-hand
-side. They are often combined like so:
-
-```rust,ignore
-macro_rules! foo {
-    () => {{
-        ...
-    }}
-}
-```
-
-The outer braces are part of the syntax of `macro_rules!`. In fact, you can use
-`()` or `[]` instead. They simply delimit the right-hand side as a whole.
-
-The inner braces are part of the expanded syntax. Remember, the `vec!` macro is
-used in an expression context. To write an expression with multiple statements,
-including `let`-bindings, we use a block. If your macro expands to a single
-expression, you don’t need this extra layer of braces.
-
-Note that we never *declared* that the macro produces an expression. In fact,
-this is not determined until we use the macro as an expression. With care, you
-can write a macro whose expansion works in several contexts. For example,
-shorthand for a data type could be valid as either an expression or a pattern.
-
-## Repetition
-
-The repetition operator follows two principal rules:
-
-1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
-   it contains, in lockstep, and
-2. each `$name` must be under at least as many `$(...)*`s as it was matched
-   against. If it is under more, it’ll be duplicated, as appropriate.
-
-This baroque macro illustrates the duplication of variables from outer
-repetition levels.
-
-```rust
-macro_rules! o_O {
-    (
-        $(
-            $x:expr; [ $( $y:expr ),* ]
-        );*
-    ) => {
-        &[ $($( $x + $y ),*),* ]
-    }
-}
-
-fn main() {
-    let a: &[i32]
-        = o_O!(10; [1, 2, 3];
-               20; [4, 5, 6]);
-
-    assert_eq!(a, [11, 12, 13, 24, 25, 26]);
-}
-```
-
-That’s most of the matcher syntax. These examples use `$(...)*`, which is a
-"zero or more" match. Alternatively you can write `$(...)+` for a "one or
-more" match. Both forms optionally include a separator, which can be any token
-except `+` or `*`.
-
-This system is based on
-"[Macro-by-Example](https://www.cs.indiana.edu/ftp/techreports/TR206.pdf)"
-(PDF link).
-
-# Hygiene
-
-Some languages implement macros using simple text substitution, which leads to
-various problems. For example, this C program prints `13` instead of the
-expected `25`.
-
-```text
-#define FIVE_TIMES(x) 5 * x
-
-int main() {
-    printf("%d\n", FIVE_TIMES(2 + 3));
-    return 0;
-}
-```
-
-After expansion we have `5 * 2 + 3`, and multiplication has greater precedence
-than addition. If you’ve used C macros a lot, you probably know the standard
-idioms for avoiding this problem, as well as five or six others. In Rust, we
-don’t have to worry about it.
-
-```rust
-macro_rules! five_times {
-    ($x:expr) => (5 * $x);
-}
-
-fn main() {
-    assert_eq!(25, five_times!(2 + 3));
-}
-```
-
-The metavariable `$x` is parsed as a single expression node, and keeps its
-place in the syntax tree even after substitution.
-
-Another common problem in macro systems is ‘variable capture’. Here’s a C
-macro using a block with multiple statements.
-
-```text
-#define LOG(msg) do { \
-    int state = get_log_state(); \
-    if (state > 0) { \
-        printf("log(%d): %s\n", state, msg); \
-    } \
-} while (0)
-```
-
-Here’s a simple use case that goes terribly wrong:
-
-```text
-const char *state = "reticulating splines";
-LOG(state);
-```
-
-This expands to
-
-```text
-const char *state = "reticulating splines";
-do {
-    int state = get_log_state();
-    if (state > 0) {
-        printf("log(%d): %s\n", state, state);
-    }
-} while (0);
-```
-
-The second variable named `state` shadows the first one.  This is a problem
-because the print statement should refer to both of them.
-
-The equivalent Rust macro has the desired behavior.
-
-```rust
-# fn get_log_state() -> i32 { 3 }
-macro_rules! log {
-    ($msg:expr) => {{
-        let state: i32 = get_log_state();
-        if state > 0 {
-            println!("log({}): {}", state, $msg);
-        }
-    }};
-}
-
-fn main() {
-    let state: &str = "reticulating splines";
-    log!(state);
-}
-```
-
-This works because Rust has a [hygienic macro system]. Each macro expansion
-happens in a distinct ‘syntax context’, and each variable is tagged with the
-syntax context where it was introduced. It’s as though the variable `state`
-inside `main` is painted a different "color" from the variable `state` inside
-the macro, and therefore they don’t conflict.
-
-[hygienic macro system]: https://en.wikipedia.org/wiki/Hygienic_macro
-
-This also restricts the ability of macros to introduce new bindings at the
-invocation site. Code such as the following will not work:
-
-```rust,ignore
-macro_rules! foo {
-    () => (let x = 3;);
-}
-
-fn main() {
-    foo!();
-    println!("{}", x);
-}
-```
-
-Instead you need to pass the variable name into the invocation, so that it’s
-tagged with the right syntax context.
-
-```rust
-macro_rules! foo {
-    ($v:ident) => (let $v = 3;);
-}
-
-fn main() {
-    foo!(x);
-    println!("{}", x);
-}
-```
-
-This holds for `let` bindings and loop labels, but not for [items][items].
-So the following code does compile:
-
-```rust
-macro_rules! foo {
-    () => (fn x() { });
-}
-
-fn main() {
-    foo!();
-    x();
-}
-```
-
-[items]: ../reference/items.html
-
-# Recursive macros
-
-A macro’s expansion can include more macro invocations, including invocations
-of the very same macro being expanded.  These recursive macros are useful for
-processing tree-structured input, as illustrated by this (simplistic) HTML
-shorthand:
-
-```rust
-# #![allow(unused_must_use)]
-macro_rules! write_html {
-    ($w:expr, ) => (());
-
-    ($w:expr, $e:tt) => (write!($w, "{}", $e));
-
-    ($w:expr, $tag:ident [ $($inner:tt)* ] $($rest:tt)*) => {{
-        write!($w, "<{}>", stringify!($tag));
-        write_html!($w, $($inner)*);
-        write!($w, "</{}>", stringify!($tag));
-        write_html!($w, $($rest)*);
-    }};
-}
-
-fn main() {
-#   // FIXME(#21826)
-    use std::fmt::Write;
-    let mut out = String::new();
-
-    write_html!(&mut out,
-        html[
-            head[title["Macros guide"]]
-            body[h1["Macros are the best!"]]
-        ]);
-
-    assert_eq!(out,
-        "<html><head><title>Macros guide</title></head>\
-         <body><h1>Macros are the best!</h1></body></html>");
-}
-```
-
-# Debugging macro code
-
-To see the results of expanding macros, run `rustc --pretty expanded`. The
-output represents a whole crate, so you can also feed it back in to `rustc`,
-which will sometimes produce better error messages than the original
-compilation. Note that the `--pretty expanded` output may have a different
-meaning if multiple variables of the same name (but different syntax contexts)
-are in play in the same scope. In this case `--pretty expanded,hygiene` will
-tell you about the syntax contexts.
-
-`rustc` provides two syntax extensions that help with macro debugging. For now,
-they are unstable and require feature gates.
-
-* `log_syntax!(...)` will print its arguments to standard output, at compile
-  time, and "expand" to nothing.
-
-* `trace_macros!(true)` will enable a compiler message every time a macro is
-  expanded. Use `trace_macros!(false)` later in expansion to turn it off.
-
-# Syntactic requirements
-
-Even when Rust code contains un-expanded macros, it can be parsed as a full
-[syntax tree][ast]. This property can be very useful for editors and other
-tools that process code. It also has a few consequences for the design of
-Rust’s macro system.
-
-[ast]: glossary.html#abstract-syntax-tree
-
-One consequence is that Rust must determine, when it parses a macro invocation,
-whether the macro stands in for
-
-* zero or more items,
-* zero or more methods,
-* an expression,
-* a statement, or
-* a pattern.
-
-A macro invocation within a block could stand for some items, or for an
-expression / statement. Rust uses a simple rule to resolve this ambiguity. A
-macro invocation that stands for items must be either
-
-* delimited by curly braces, e.g. `foo! { ... }`, or
-* terminated by a semicolon, e.g. `foo!(...);`
-
-Another consequence of pre-expansion parsing is that the macro invocation must
-consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
-must be balanced within a macro invocation. For example, `foo!([)` is
-forbidden. This allows Rust to know where the macro invocation ends.
-
-More formally, the macro invocation body must be a sequence of ‘token trees’.
-A token tree is defined recursively as either
-
-* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
-* any other single token.
-
-Within a matcher, each metavariable has a ‘fragment specifier’, identifying
-which syntactic form it matches.
-
-* `ident`: an identifier. Examples: `x`; `foo`.
-* `path`: a qualified name. Example: `T::SpecialA`.
-* `expr`: an expression. Examples: `2 + 2`; `if true { 1 } else { 2 }`; `f(42)`.
-* `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`.
-* `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`.
-* `stmt`: a single statement. Example: `let x = 3`.
-* `block`: a brace-delimited sequence of statements and optionally an expression. Example:
-  `{ log(error, "hi"); return 12; }`.
-* `item`: an [item][item]. Examples: `fn foo() { }`; `struct Bar;`.
-* `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`.
-* `tt`: a single token tree.
-
-There are additional rules regarding the next token after a metavariable:
-
-* `expr` and `stmt` variables may only be followed by one of: `=> , ;`
-* `ty` and `path` variables may only be followed by one of: `=> , = | ; : > [ { as where`
-* `pat` variables may only be followed by one of: `=> , = | if in`
-* Other variables may be followed by any token.
-
-These rules provide some flexibility for Rust’s syntax to evolve without
-breaking existing macros.
-
-The macro system does not deal with parse ambiguity at all. For example, the
-grammar `$($i:ident)* $e:expr` will always fail to parse, because the parser would
-be forced to choose between parsing `$i` and parsing `$e`. Changing the
-invocation syntax to put a distinctive token in front can solve the problem. In
-this case, you can write `$(I $i:ident)* E $e:expr`.
-
-[item]: ../reference/items.html
-
-# Scoping and macro import/export
-
-Macros are expanded at an early stage in compilation, before name resolution.
-One downside is that scoping works differently for macros, compared to other
-constructs in the language.
-
-Definition and expansion of macros both happen in a single depth-first,
-lexical-order traversal of a crate’s source. So a macro defined at module scope
-is visible to any subsequent code in the same module, which includes the body
-of any subsequent child `mod` items.
-
-A macro defined within the body of a single `fn`, or anywhere else not at
-module scope, is visible only within that item.
-
-If a module has the `macro_use` attribute, its macros are also visible in its
-parent module after the child’s `mod` item. If the parent also has `macro_use`
-then the macros will be visible in the grandparent after the parent’s `mod`
-item, and so forth.
-
-The `macro_use` attribute can also appear on `extern crate`. In this context
-it controls which macros are loaded from the external crate, e.g.
-
-```rust,ignore
-#[macro_use(foo, bar)]
-extern crate baz;
-```
-
-If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
-there is no `#[macro_use]` attribute then no macros are loaded. Only macros
-defined with the `#[macro_export]` attribute may be loaded.
-
-To load a crate’s macros without linking it into the output, use `#[no_link]`
-as well.
-
-An example:
-
-```rust
-macro_rules! m1 { () => (()) }
-
-// Visible here: `m1`.
-
-mod foo {
-    // Visible here: `m1`.
-
-    #[macro_export]
-    macro_rules! m2 { () => (()) }
-
-    // Visible here: `m1`, `m2`.
-}
-
-// Visible here: `m1`.
-
-macro_rules! m3 { () => (()) }
-
-// Visible here: `m1`, `m3`.
-
-#[macro_use]
-mod bar {
-    // Visible here: `m1`, `m3`.
-
-    macro_rules! m4 { () => (()) }
-
-    // Visible here: `m1`, `m3`, `m4`.
-}
-
-// Visible here: `m1`, `m3`, `m4`.
-# fn main() { }
-```
-
-When this library is loaded with `#[macro_use] extern crate`, only `m2` will
-be imported.
-
-The Rust Reference has a [listing of macro-related
-attributes](../reference/attributes.html#macro-related-attributes).
-
-# The variable `$crate`
-
-A further difficulty occurs when a macro is used in multiple crates. Say that
-`mylib` defines
-
-```rust
-pub fn increment(x: u32) -> u32 {
-    x + 1
-}
-
-#[macro_export]
-macro_rules! inc_a {
-    ($x:expr) => ( ::increment($x) )
-}
-
-#[macro_export]
-macro_rules! inc_b {
-    ($x:expr) => ( ::mylib::increment($x) )
-}
-# fn main() { }
-```
-
-`inc_a` only works within `mylib`, while `inc_b` only works outside the
-library. Furthermore, `inc_b` will break if the user imports `mylib` under
-another name.
-
-Rust does not (yet) have a hygiene system for crate references, but it does
-provide a simple workaround for this problem. Within a macro imported from a
-crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
-By contrast, when a macro is defined and then used in the same crate, `$crate`
-will expand to nothing. This means we can write
-
-```rust
-#[macro_export]
-macro_rules! inc {
-    ($x:expr) => ( $crate::increment($x) )
-}
-# fn main() { }
-```
-
-to define a single macro that works both inside and outside our library. The
-function name will expand to either `::increment` or `::mylib::increment`.
-
-To keep this system simple and correct, `#[macro_use] extern crate ...` may
-only appear at the root of your crate, not inside `mod`.
-
-# The deep end
-
-The introductory chapter mentioned recursive macros, but it did not give the
-full story. Recursive macros are useful for another reason: Each recursive
-invocation gives you another opportunity to pattern-match the macro’s
-arguments.
-
-As an extreme example, it is possible, though hardly advisable, to implement
-the [Bitwise Cyclic Tag](https://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
-within Rust’s macro system.
-
-```rust
-macro_rules! bct {
-    // cmd 0:  d ... => ...
-    (0, $($ps:tt),* ; $_d:tt)
-        => (bct!($($ps),*, 0 ; ));
-    (0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
-        => (bct!($($ps),*, 0 ; $($ds),*));
-
-    // cmd 1p:  1 ... => 1 ... p
-    (1, $p:tt, $($ps:tt),* ; 1)
-        => (bct!($($ps),*, 1, $p ; 1, $p));
-    (1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
-        => (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
-
-    // cmd 1p:  0 ... => 0 ...
-    (1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
-        => (bct!($($ps),*, 1, $p ; $($ds),*));
-
-    // Halt on empty data string:
-    ( $($ps:tt),* ; )
-        => (());
-}
-```
-
-Exercise: use macros to reduce duplication in the above definition of the
-`bct!` macro.
-
-# Common macros
-
-Here are some common macros you’ll see in Rust code.
-
-## panic!
-
-This macro causes the current thread to panic. You can give it a message
-to panic with:
-
-```rust,should_panic
-panic!("oh no!");
-```
-
-## vec!
-
-The `vec!` macro is used throughout the book, so you’ve probably seen it
-already. It creates `Vec<T>`s with ease:
-
-```rust
-let v = vec![1, 2, 3, 4, 5];
-```
-
-It also lets you make vectors with repeating values. For example, a hundred
-zeroes:
-
-```rust
-let v = vec![0; 100];
-```
-
-## assert! and assert_eq!
-
-These two macros are used in tests. `assert!` takes a boolean. `assert_eq!`
-takes two values and checks them for equality. `true` passes, `false` `panic!`s.
-Like this:
-
-```rust,should_panic
-// A-ok!
-
-assert!(true);
-assert_eq!(5, 3 + 2);
-
-// Nope :(
-
-assert!(5 < 3);
-assert_eq!(5, 3);
-```
-
-## try!
-
-`try!` is used for error handling. It takes something that can return a
-`Result<T, E>`, and gives `T` if it’s a `Ok<T>`, and `return`s with the
-`Err(E)` if it’s that. Like this:
-
-```rust,no_run
-use std::fs::File;
-
-fn foo() -> std::io::Result<()> {
-    let f = try!(File::create("foo.txt"));
-
-    Ok(())
-}
-```
-
-This is cleaner than doing this:
-
-```rust,no_run
-use std::fs::File;
-
-fn foo() -> std::io::Result<()> {
-    let f = File::create("foo.txt");
-
-    let f = match f {
-        Ok(t) => t,
-        Err(e) => return Err(e),
-    };
-
-    Ok(())
-}
-```
-
-## unreachable!
-
-This macro is used when you think some code should never execute:
-
-```rust
-if false {
-    unreachable!();
-}
-```
-
-Sometimes, the compiler may make you have a different branch that you know
-will never, ever run. In these cases, use this macro, so that if you end
-up wrong, you’ll get a `panic!` about it.
-
-```rust
-let x: Option<i32> = None;
-
-match x {
-    Some(_) => unreachable!(),
-    None => println!("I know x is None!"),
-}
-```
-
-## unimplemented!
-
-The `unimplemented!` macro can be used when you’re trying to get your functions
-to typecheck, and don’t want to worry about writing out the body of the
-function. One example of this situation is implementing a trait with multiple
-required methods, where you want to tackle one at a time. Define the others
-as `unimplemented!` until you’re ready to write them.
diff --git a/src/doc/book/src/match.md b/src/doc/book/src/match.md
deleted file mode 100644 (file)
index b1e26a9..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-# Match
-
-Often, a simple [`if`][if]/`else` isn’t enough, because you have more than two
-possible options. Also, conditions can get quite complex. Rust
-has a keyword, `match`, that allows you to replace complicated `if`/`else`
-groupings with something more powerful. Check it out:
-
-```rust
-let x = 5;
-
-match x {
-    1 => println!("one"),
-    2 => println!("two"),
-    3 => println!("three"),
-    4 => println!("four"),
-    5 => println!("five"),
-    _ => println!("something else"),
-}
-```
-
-[if]: if.html
-
-`match` takes an expression and then branches based on its value. Each ‘arm’ of
-the branch is of the form `val => expression`. When the value matches, that arm’s
-expression will be evaluated. It’s called `match` because of the term ‘pattern
-matching’, which `match` is an implementation of. There’s a [separate section on
-patterns][patterns] that covers all the patterns that are possible here.
-
-[patterns]: patterns.html
-
-One of the many advantages of `match` is it enforces ‘exhaustiveness checking’.
-For example if we remove the last arm with the underscore `_`, the compiler will
-give us an error:
-
-```text
-error: non-exhaustive patterns: `_` not covered
-```
-
-Rust is telling us that we forgot some value. The compiler infers from `x` that it
-can have any 32bit integer value; for example -2,147,483,648 to 2,147,483,647. The `_` acts 
-as a 'catch-all', and will catch all possible values that *aren't* specified in 
-an arm of `match`. As you can see in the previous example, we provide `match` 
-arms for integers 1-5, if `x` is 6 or any other value, then it is caught by `_`.
-
-`match` is also an expression, which means we can use it on the right-hand
-side of a `let` binding or directly where an expression is used:
-
-```rust
-let x = 5;
-
-let number = match x {
-    1 => "one",
-    2 => "two",
-    3 => "three",
-    4 => "four",
-    5 => "five",
-    _ => "something else",
-};
-```
-
-Sometimes it’s a nice way of converting something from one type to another; in
-this example the integers are converted to `String`.
-
-# Matching on enums
-
-Another important use of the `match` keyword is to process the possible
-variants of an enum:
-
-```rust
-enum Message {
-    Quit,
-    ChangeColor(i32, i32, i32),
-    Move { x: i32, y: i32 },
-    Write(String),
-}
-
-fn quit() { /* ... */ }
-fn change_color(r: i32, g: i32, b: i32) { /* ... */ }
-fn move_cursor(x: i32, y: i32) { /* ... */ }
-
-fn process_message(msg: Message) {
-    match msg {
-        Message::Quit => quit(),
-        Message::ChangeColor(r, g, b) => change_color(r, g, b),
-        Message::Move { x, y: new_name_for_y } => move_cursor(x, new_name_for_y),
-        Message::Write(s) => println!("{}", s),
-    };
-}
-```
-
-Again, the Rust compiler checks exhaustiveness, so it demands that you
-have a match arm for every variant of the enum. If you leave one off, it
-will give you a compile-time error unless you use `_` or provide all possible
-arms.
-
-Unlike the previous uses of `match`, you can’t use the normal `if`
-statement to do this. You can use the [`if let`][if-let] statement,
-which can be seen as an abbreviated form of `match`.
-
-[if-let]: if-let.html
diff --git a/src/doc/book/src/method-syntax.md b/src/doc/book/src/method-syntax.md
deleted file mode 100644 (file)
index 0404a5c..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-# Method Syntax
-
-Functions are great, but if you want to call a bunch of them on some data, it
-can be awkward. Consider this code:
-
-```rust,ignore
-baz(bar(foo));
-```
-
-We would read this left-to-right, and so we see ‘baz bar foo’. But this isn’t the
-order that the functions would get called in, that’s inside-out: ‘foo bar baz’.
-Wouldn’t it be nice if we could do this instead?
-
-```rust,ignore
-foo.bar().baz();
-```
-
-Luckily, as you may have guessed with the leading question, you can! Rust provides
-the ability to use this ‘method call syntax’ via the `impl` keyword.
-
-# Method calls
-
-Here’s how it works:
-
-```rust
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-impl Circle {
-    fn area(&self) -> f64 {
-        std::f64::consts::PI * (self.radius * self.radius)
-    }
-}
-
-fn main() {
-    let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
-    println!("{}", c.area());
-}
-```
-
-This will print `12.566371`.
-
-We’ve made a `struct` that represents a circle. We then write an `impl` block,
-and inside it, define a method, `area`.
-
-Methods take a special first parameter, of which there are three variants:
-`self`, `&self`, and `&mut self`. You can think of this first parameter as
-being the `foo` in `foo.bar()`. The three variants correspond to the three
-kinds of things `foo` could be: `self` if it’s a value on the stack,
-`&self` if it’s a reference, and `&mut self` if it’s a mutable reference.
-Because we took the `&self` parameter to `area`, we can use it like any
-other parameter. Because we know it’s a `Circle`, we can access the `radius`
-like we would with any other `struct`.
-
-We should default to using `&self`, as you should prefer borrowing over taking
-ownership, as well as taking immutable references over mutable ones. Here’s an
-example of all three variants:
-
-```rust
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-impl Circle {
-    fn reference(&self) {
-       println!("taking self by reference!");
-    }
-
-    fn mutable_reference(&mut self) {
-       println!("taking self by mutable reference!");
-    }
-
-    fn takes_ownership(self) {
-       println!("taking ownership of self!");
-    }
-}
-```
-
-You can use as many `impl` blocks as you’d like. The previous example could
-have also been written like this:
-
-```rust
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-impl Circle {
-    fn reference(&self) {
-       println!("taking self by reference!");
-    }
-}
-
-impl Circle {
-    fn mutable_reference(&mut self) {
-       println!("taking self by mutable reference!");
-    }
-}
-
-impl Circle {
-    fn takes_ownership(self) {
-       println!("taking ownership of self!");
-    }
-}
-```
-
-# Chaining method calls
-
-So, now we know how to call a method, such as `foo.bar()`. But what about our
-original example, `foo.bar().baz()`? This is called ‘method chaining’. Let’s
-look at an example:
-
-```rust
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-impl Circle {
-    fn area(&self) -> f64 {
-        std::f64::consts::PI * (self.radius * self.radius)
-    }
-
-    fn grow(&self, increment: f64) -> Circle {
-        Circle { x: self.x, y: self.y, radius: self.radius + increment }
-    }
-}
-
-fn main() {
-    let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
-    println!("{}", c.area());
-
-    let d = c.grow(2.0).area();
-    println!("{}", d);
-}
-```
-
-Check the return type:
-
-```rust
-# struct Circle;
-# impl Circle {
-fn grow(&self, increment: f64) -> Circle {
-# Circle } }
-```
-
-We say we’re returning a `Circle`. With this method, we can grow a new
-`Circle` to any arbitrary size.
-
-# Associated functions
-
-You can also define associated functions that do not take a `self` parameter.
-Here’s a pattern that’s very common in Rust code:
-
-```rust
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-impl Circle {
-    fn new(x: f64, y: f64, radius: f64) -> Circle {
-        Circle {
-            x: x,
-            y: y,
-            radius: radius,
-        }
-    }
-}
-
-fn main() {
-    let c = Circle::new(0.0, 0.0, 2.0);
-}
-```
-
-This ‘associated function’ builds a new `Circle` for us. Note that associated
-functions are called with the `Struct::function()` syntax, rather than the
-`ref.method()` syntax. Some other languages call associated functions ‘static
-methods’.
-
-# Builder Pattern
-
-Let’s say that we want our users to be able to create `Circle`s, but we will
-allow them to only set the properties they care about. Otherwise, the `x`
-and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn’t
-have method overloading, named arguments, or variable arguments. We employ
-the builder pattern instead. It looks like this:
-
-```rust
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-impl Circle {
-    fn area(&self) -> f64 {
-        std::f64::consts::PI * (self.radius * self.radius)
-    }
-}
-
-struct CircleBuilder {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-impl CircleBuilder {
-    fn new() -> CircleBuilder {
-        CircleBuilder { x: 0.0, y: 0.0, radius: 1.0, }
-    }
-
-    fn x(&mut self, coordinate: f64) -> &mut CircleBuilder {
-        self.x = coordinate;
-        self
-    }
-
-    fn y(&mut self, coordinate: f64) -> &mut CircleBuilder {
-        self.y = coordinate;
-        self
-    }
-
-    fn radius(&mut self, radius: f64) -> &mut CircleBuilder {
-        self.radius = radius;
-        self
-    }
-
-    fn finalize(&self) -> Circle {
-        Circle { x: self.x, y: self.y, radius: self.radius }
-    }
-}
-
-fn main() {
-    let c = CircleBuilder::new()
-                .x(1.0)
-                .y(2.0)
-                .radius(2.0)
-                .finalize();
-
-    println!("area: {}", c.area());
-    println!("x: {}", c.x);
-    println!("y: {}", c.y);
-}
-```
-
-What we’ve done here is make another `struct`, `CircleBuilder`. We’ve defined our
-builder methods on it. We’ve also defined our `area()` method on `Circle`. We
-also made one more method on `CircleBuilder`: `finalize()`. This method creates
-our final `Circle` from the builder. Now, we’ve used the type system to enforce
-our concerns: we can use the methods on `CircleBuilder` to constrain making
-`Circle`s in any way we choose.
diff --git a/src/doc/book/src/mutability.md b/src/doc/book/src/mutability.md
deleted file mode 100644 (file)
index fa7a259..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-# Mutability
-
-Mutability, the ability to change something, works a bit differently in Rust
-than in other languages. The first aspect of mutability is its non-default
-status:
-
-```rust,ignore
-let x = 5;
-x = 6; // Error!
-```
-
-We can introduce mutability with the `mut` keyword:
-
-```rust
-let mut x = 5;
-
-x = 6; // No problem!
-```
-
-This is a mutable [variable binding][vb]. When a binding is mutable, it means
-you’re allowed to change what the binding points to. So in the above example,
-it’s not so much that the value at `x` is changing, but that the binding
-changed from one `i32` to another.
-
-[vb]: variable-bindings.html
-
-You can also create a [reference][ref] to it, using `&x`, but if you want to use the reference to change it, you will need a mutable reference:
-
-```rust
-let mut x = 5;
-let y = &mut x;
-```
-
-[ref]: references-and-borrowing.html
-
-`y` is an immutable binding to a mutable reference, which means that you can’t bind 'y' to something else (`y = &mut z`), but `y` can be used to bind `x` to something else (`*y = 5`). A subtle distinction.
-
-Of course, if you need both:
-
-```rust
-let mut x = 5;
-let mut y = &mut x;
-```
-
-Now `y` can be bound to another value, and the value it’s referencing can be
-changed.
-
-It’s important to note that `mut` is part of a [pattern][pattern], so you
-can do things like this:
-
-```rust
-let (mut x, y) = (5, 6);
-
-fn foo(mut x: i32) {
-# }
-```
-
-Note that here, the `x` is mutable, but not the `y`.
-
-[pattern]: patterns.html
-
-# Interior vs. Exterior Mutability
-
-However, when we say something is ‘immutable’ in Rust, that doesn’t mean that
-it’s not able to be changed: we are referring to its ‘exterior mutability’ that
-in this case is immutable. Consider, for example, [`Arc<T>`][arc]:
-
-```rust
-use std::sync::Arc;
-
-let x = Arc::new(5);
-let y = x.clone();
-```
-
-[arc]: ../std/sync/struct.Arc.html
-
-When we call `clone()`, the `Arc<T>` needs to update the reference count. Yet
-we’ve not used any `mut`s here, `x` is an immutable binding, and we didn’t take
-`&mut 5` or anything. So what gives?
-
-To understand this, we have to go back to the core of Rust’s guiding
-philosophy, memory safety, and the mechanism by which Rust guarantees it, the
-[ownership][ownership] system, and more specifically, [borrowing][borrowing]:
-
-> You may have one or the other of these two kinds of borrows, but not both at
-> the same time:
->
-> * one or more references (`&T`) to a resource,
-> * exactly one mutable reference (`&mut T`).
-
-[ownership]: ownership.html
-[borrowing]: references-and-borrowing.html#borrowing
-
-So, that’s the real definition of ‘immutability’: is this safe to have two
-pointers to? In `Arc<T>`’s case, yes: the mutation is entirely contained inside
-the structure itself. It’s not user facing. For this reason, it hands out `&T`
-with `clone()`. If it handed out `&mut T`s, though, that would be a problem.
-
-Other types, like the ones in the [`std::cell`][stdcell] module, have the
-opposite: interior mutability. For example:
-
-```rust
-use std::cell::RefCell;
-
-let x = RefCell::new(42);
-
-let y = x.borrow_mut();
-```
-
-[stdcell]: ../std/cell/index.html
-
-RefCell hands out `&mut` references to what’s inside of it with the
-`borrow_mut()` method. Isn’t that dangerous? What if we do:
-
-```rust,ignore
-use std::cell::RefCell;
-
-let x = RefCell::new(42);
-
-let y = x.borrow_mut();
-let z = x.borrow_mut();
-# (y, z);
-```
-
-This will in fact panic, at runtime. This is what `RefCell` does: it enforces
-Rust’s borrowing rules at runtime, and `panic!`s if they’re violated. This
-allows us to get around another aspect of Rust’s mutability rules. Let’s talk
-about it first.
-
-## Field-level mutability
-
-Mutability is a property of either a borrow (`&mut`) or a binding (`let mut`).
-This means that, for example, you cannot have a [`struct`][struct] with
-some fields mutable and some immutable:
-
-```rust,ignore
-struct Point {
-    x: i32,
-    mut y: i32, // Nope.
-}
-```
-
-The mutability of a struct is in its binding:
-
-```rust,ignore
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-let mut a = Point { x: 5, y: 6 };
-
-a.x = 10;
-
-let b = Point { x: 5, y: 6};
-
-b.x = 10; // Error: cannot assign to immutable field `b.x`.
-```
-
-[struct]: structs.html
-
-However, by using [`Cell<T>`][cell], you can emulate field-level mutability:
-
-```rust
-use std::cell::Cell;
-
-struct Point {
-    x: i32,
-    y: Cell<i32>,
-}
-
-let point = Point { x: 5, y: Cell::new(6) };
-
-point.y.set(7);
-
-println!("y: {:?}", point.y);
-```
-
-[cell]: ../std/cell/struct.Cell.html
-
-This will print `y: Cell { value: 7 }`. We’ve successfully updated `y`.
diff --git a/src/doc/book/src/operators-and-overloading.md b/src/doc/book/src/operators-and-overloading.md
deleted file mode 100644 (file)
index a69cd6a..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-# Operators and Overloading
-
-Rust allows for a limited form of operator overloading. There are certain
-operators that are able to be overloaded. To support a particular operator
-between types, there’s a specific trait that you can implement, which then
-overloads the operator.
-
-For example, the `+` operator can be overloaded with the `Add` trait:
-
-```rust
-use std::ops::Add;
-
-#[derive(Debug)]
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-impl Add for Point {
-    type Output = Point;
-
-    fn add(self, other: Point) -> Point {
-        Point { x: self.x + other.x, y: self.y + other.y }
-    }
-}
-
-fn main() {
-    let p1 = Point { x: 1, y: 0 };
-    let p2 = Point { x: 2, y: 3 };
-
-    let p3 = p1 + p2;
-
-    println!("{:?}", p3);
-}
-```
-
-In `main`, we can use `+` on our two `Point`s, since we’ve implemented
-`Add<Output=Point>` for `Point`.
-
-There are a number of operators that can be overloaded this way, and all of
-their associated traits live in the [`std::ops`][stdops] module. Check out its
-documentation for the full list.
-
-[stdops]: ../std/ops/index.html
-
-Implementing these traits follows a pattern. Let’s look at [`Add`][add] in more
-detail:
-
-```rust
-# mod foo {
-pub trait Add<RHS = Self> {
-    type Output;
-
-    fn add(self, rhs: RHS) -> Self::Output;
-}
-# }
-```
-
-[add]: ../std/ops/trait.Add.html
-
-There’s three types in total involved here: the type you `impl Add` for, `RHS`,
-which defaults to `Self`, and `Output`. For an expression `let z = x + y`, `x`
-is the `Self` type, `y` is the RHS, and `z` is the `Self::Output` type.
-
-```rust
-# struct Point;
-# use std::ops::Add;
-impl Add<i32> for Point {
-    type Output = f64;
-
-    fn add(self, rhs: i32) -> f64 {
-        // Add an i32 to a Point and get an f64.
-# 1.0
-    }
-}
-```
-
-will let you do this:
-
-```rust,ignore
-let p: Point = // ...
-let x: f64 = p + 2i32;
-```
-
-# Using operator traits in generic structs
-
-Now that we know how operator traits are defined, we can define our `HasArea`
-trait and `Square` struct from the [traits chapter][traits] more generically:
-
-[traits]: traits.html
-
-```rust
-use std::ops::Mul;
-
-trait HasArea<T> {
-    fn area(&self) -> T;
-}
-
-struct Square<T> {
-    x: T,
-    y: T,
-    side: T,
-}
-
-impl<T> HasArea<T> for Square<T>
-        where T: Mul<Output=T> + Copy {
-    fn area(&self) -> T {
-        self.side * self.side
-    }
-}
-
-fn main() {
-    let s = Square {
-        x: 0.0f64,
-        y: 0.0f64,
-        side: 12.0f64,
-    };
-
-    println!("Area of s: {}", s.area());
-}
-```
-
-For `HasArea` and `Square`, we declare a type parameter `T` and replace
-`f64` with it. The `impl` needs more involved modifications:
-
-```rust,ignore
-impl<T> HasArea<T> for Square<T>
-        where T: Mul<Output=T> + Copy { ... }
-```
-
-The `area` method requires that we can multiply the sides, so we declare that
-type `T` must implement `std::ops::Mul`. Like `Add`, mentioned above, `Mul`
-itself takes an `Output` parameter: since we know that numbers don't change
-type when multiplied, we also set it to `T`. `T` must also support copying, so
-Rust doesn't try to move `self.side` into the return value.
diff --git a/src/doc/book/src/ownership.md b/src/doc/book/src/ownership.md
deleted file mode 100644 (file)
index 21ebd63..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-# Ownership
-
-This is the first of three sections presenting Rust’s ownership system. This is one of
-Rust’s most distinct and compelling features, with which Rust developers should
-become quite acquainted. Ownership is how Rust achieves its largest goal,
-memory safety. There are a few distinct concepts, each with its own
-chapter:
-
-* ownership, which you’re reading now
-* [borrowing][borrowing], and their associated feature ‘references’
-* [lifetimes][lifetimes], an advanced concept of borrowing
-
-These three chapters are related, and in order. You’ll need all three to fully
-understand the ownership system.
-
-[borrowing]: references-and-borrowing.html
-[lifetimes]: lifetimes.html
-
-# Meta
-
-Before we get to the details, two important notes about the ownership system.
-
-Rust has a focus on safety and speed. It accomplishes these goals through many
-‘zero-cost abstractions’, which means that in Rust, abstractions cost as little
-as possible in order to make them work. The ownership system is a prime example
-of a zero-cost abstraction. All of the analysis we’ll talk about in this guide
-is _done at compile time_. You do not pay any run-time cost for any of these
-features.
-
-However, this system does have a certain cost: learning curve. Many new users
-to Rust experience something we like to call ‘fighting with the borrow
-checker’, where the Rust compiler refuses to compile a program that the author
-thinks is valid. This often happens because the programmer’s mental model of
-how ownership should work doesn’t match the actual rules that Rust implements.
-You probably will experience similar things at first. There is good news,
-however: more experienced Rust developers report that once they work with the
-rules of the ownership system for a period of time, they fight the borrow
-checker less and less.
-
-With that in mind, let’s learn about ownership.
-
-# Ownership
-
-[Variable bindings][bindings] have a property in Rust: they ‘have ownership’
-of what they’re bound to. This means that when a binding goes out of scope,
-Rust will free the bound resources. For example:
-
-```rust
-fn foo() {
-    let v = vec![1, 2, 3];
-}
-```
-
-When `v` comes into scope, a new [vector][vectors] is created on [the stack][stack],
-and it allocates space on [the heap][heap] for its elements. When `v` goes out
-of scope at the end of `foo()`, Rust will clean up everything related to the
-vector, even the heap-allocated memory. This happens deterministically, at the
-end of the scope.
-
-We covered [vectors] in the previous chapter; we use them
-here as an example of a type that allocates space on the heap at runtime. They
-behave like [arrays], except their size may change by `push()`ing more
-elements onto them.
-
-Vectors have a [generic type][generics] `Vec<T>`, so in this example `v` will have type
-`Vec<i32>`. We'll cover [generics] in detail in a later chapter.
-
-[arrays]: primitive-types.html#arrays
-[vectors]: vectors.html
-[heap]: the-stack-and-the-heap.html#the-heap
-[stack]: the-stack-and-the-heap.html#the-stack
-[bindings]: variable-bindings.html
-[generics]: generics.html
-
-# Move semantics
-
-There’s some more subtlety here, though: Rust ensures that there is _exactly
-one_ binding to any given resource. For example, if we have a vector, we can
-assign it to another binding:
-
-```rust
-let v = vec![1, 2, 3];
-
-let v2 = v;
-```
-
-But, if we try to use `v` afterwards, we get an error:
-
-```rust,ignore
-let v = vec![1, 2, 3];
-
-let v2 = v;
-
-println!("v[0] is: {}", v[0]);
-```
-
-It looks like this:
-
-```text
-error: use of moved value: `v`
-println!("v[0] is: {}", v[0]);
-                        ^
-```
-
-A similar thing happens if we define a function which takes ownership, and
-try to use something after we’ve passed it as an argument:
-
-```rust,ignore
-fn take(v: Vec<i32>) {
-    // What happens here isn’t important.
-}
-
-let v = vec![1, 2, 3];
-
-take(v);
-
-println!("v[0] is: {}", v[0]);
-```
-
-Same error: ‘use of moved value’. When we transfer ownership to something else,
-we say that we’ve ‘moved’ the thing we refer to. You don’t need some sort of
-special annotation here, it’s the default thing that Rust does.
-
-## The details
-
-The reason that we cannot use a binding after we’ve moved it is subtle, but
-important.
-
-When we write code like this:
-
-```rust
-let x = 10;
-```
-
-Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit
-pattern representing the value of 10 to the allocated memory and binds the
-variable name x to this memory region for future reference.
-
-[i32]: primitive-types.html#numeric-types
-
-Now consider the following code fragment:
-
-```rust
-let v = vec![1, 2, 3];
-
-let mut v2 = v;
-```
-
-The first line allocates memory for the vector object `v` on the stack like
-it does for `x` above. But in addition to that it also allocates some memory
-on the [heap][sh] for the actual data (`[1, 2, 3]`). Rust copies the address
-of this heap allocation to an internal pointer, which is part of the vector
-object placed on the stack (let's call it the data pointer).
-
-It is worth pointing out (even at the risk of stating the obvious) that the
-vector object and its data live in separate memory regions instead of being a
-single contiguous memory allocation (due to reasons we will not go into at
-this point of time). These two parts of the vector (the one on the stack and
-one on the heap) must agree with each other at all times with regards to
-things like the length, capacity, etc.
-
-When we move `v` to `v2`, Rust actually does a bitwise copy of the vector
-object `v` into the stack allocation represented by `v2`. This shallow copy
-does not create a copy of the heap allocation containing the actual data.
-Which means that there would be two pointers to the contents of the vector
-both pointing to the same memory allocation on the heap. It would violate
-Rust’s safety guarantees by introducing a data race if one could access both
-`v` and `v2` at the same time.
-
-For example if we truncated the vector to just two elements through `v2`:
-
-```rust
-# let v = vec![1, 2, 3];
-# let mut v2 = v;
-v2.truncate(2);
-```
-
-and `v` were still accessible we'd end up with an invalid vector since `v`
-would not know that the heap data has been truncated. Now, the part of the
-vector `v` on the stack does not agree with the corresponding part on the
-heap. `v` still thinks there are three elements in the vector and will
-happily let us access the non existent element `v[2]` but as you might
-already know this is a recipe for disaster. Especially because it might lead
-to a segmentation fault or worse allow an unauthorized user to read from
-memory to which they don't have access.
-
-This is why Rust forbids using `v` after we’ve done the move.
-
-[sh]: the-stack-and-the-heap.html
-
-It’s also important to note that optimizations may remove the actual copy of
-the bytes on the stack, depending on circumstances. So it may not be as
-inefficient as it initially seems.
-
-## `Copy` types
-
-We’ve established that when ownership is transferred to another binding, you
-cannot use the original binding. However, there’s a [trait][traits] that changes this
-behavior, and it’s called `Copy`. We haven’t discussed traits yet, but for now,
-you can think of them as an annotation to a particular type that adds extra
-behavior. For example:
-
-```rust
-let v = 1;
-
-let v2 = v;
-
-println!("v is: {}", v);
-```
-
-In this case, `v` is an `i32`, which implements the `Copy` trait. This means
-that, just like a move, when we assign `v` to `v2`, a copy of the data is made.
-But, unlike a move, we can still use `v` afterward. This is because an `i32`
-has no pointers to data somewhere else, copying it is a full copy.
-
-All primitive types implement the `Copy` trait and their ownership is
-therefore not moved like one would assume, following the ‘ownership rules’.
-To give an example, the two following snippets of code only compile because the
-`i32` and `bool` types implement the `Copy` trait.
-
-```rust
-fn main() {
-    let a = 5;
-
-    let _y = double(a);
-    println!("{}", a);
-}
-
-fn double(x: i32) -> i32 {
-    x * 2
-}
-```
-
-```rust
-fn main() {
-    let a = true;
-
-    let _y = change_truth(a);
-    println!("{}", a);
-}
-
-fn change_truth(x: bool) -> bool {
-    !x
-}
-```
-
-If we had used types that do not implement the `Copy` trait,
-we would have gotten a compile error because we tried to use a moved value.
-
-```text
-error: use of moved value: `a`
-println!("{}", a);
-               ^
-```
-
-We will discuss how to make your own types `Copy` in the [traits][traits]
-section.
-
-[traits]: traits.html
-
-# More than ownership
-
-Of course, if we had to hand ownership back with every function we wrote:
-
-```rust
-fn foo(v: Vec<i32>) -> Vec<i32> {
-    // Do stuff with `v`.
-
-    // Hand back ownership.
-    v
-}
-```
-
-This would get very tedious. It gets worse the more things we want to take ownership of:
-
-```rust
-fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
-    // Do stuff with `v1` and `v2`.
-
-    // Hand back ownership, and the result of our function.
-    (v1, v2, 42)
-}
-
-let v1 = vec![1, 2, 3];
-let v2 = vec![1, 2, 3];
-
-let (v1, v2, answer) = foo(v1, v2);
-```
-
-Ugh! The return type, return line, and calling the function gets way more
-complicated.
-
-Luckily, Rust offers a feature which helps us solve this problem.
-It’s called borrowing and is the topic of the next section!
-
diff --git a/src/doc/book/src/patterns.md b/src/doc/book/src/patterns.md
deleted file mode 100644 (file)
index 1983927..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-# Patterns
-
-Patterns are quite common in Rust. We use them in [variable
-bindings][bindings], [match expressions][match], and other places, too. Let’s go
-on a whirlwind tour of all of the things patterns can do!
-
-[bindings]: variable-bindings.html
-[match]: match.html
-
-A quick refresher: you can match against literals directly, and `_` acts as an
-‘any’ case:
-
-```rust
-let x = 1;
-
-match x {
-    1 => println!("one"),
-    2 => println!("two"),
-    3 => println!("three"),
-    _ => println!("anything"),
-}
-```
-
-This prints `one`.
-
-It's possible to create a binding for the value in the any case:
-
-```rust
-let x = 1;
-
-match x {
-    y => println!("x: {} y: {}", x, y),
-}
-```
-
-This prints:
-
-```text
-x: 1 y: 1
-```
-
-Note it is an error to have both a catch-all `_` and a catch-all binding in the same match block:
-
-```rust
-let x = 1;
-
-match x {
-    y => println!("x: {} y: {}", x, y),
-    _ => println!("anything"), // this causes an error as it is unreachable
-}
-```
-
-There’s one pitfall with patterns: like anything that introduces a new binding,
-they introduce shadowing. For example:
-
-```rust
-let x = 1;
-let c = 'c';
-
-match c {
-    x => println!("x: {} c: {}", x, c),
-}
-
-println!("x: {}", x)
-```
-
-This prints:
-
-```text
-x: c c: c
-x: 1
-```
-
-In other words, `x =>` matches the pattern and introduces a new binding named
-`x`. This new binding is in scope for the match arm and takes on the value of
-`c`. Notice that the value of `x` outside the scope of the match has no bearing
-on the value of `x` within it. Because we already have a binding named `x`, this
-new `x` shadows it.
-
-# Multiple patterns
-
-You can match multiple patterns with `|`:
-
-```rust
-let x = 1;
-
-match x {
-    1 | 2 => println!("one or two"),
-    3 => println!("three"),
-    _ => println!("anything"),
-}
-```
-
-This prints `one or two`.
-
-# Destructuring
-
-If you have a compound data type, like a [`struct`][struct], you can destructure it
-inside of a pattern:
-
-```rust
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-let origin = Point { x: 0, y: 0 };
-
-match origin {
-    Point { x, y } => println!("({},{})", x, y),
-}
-```
-
-[struct]: structs.html
-
-We can use `:` to give a value a different name.
-
-```rust
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-let origin = Point { x: 0, y: 0 };
-
-match origin {
-    Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
-}
-```
-
-If we only care about some of the values, we don’t have to give them all names:
-
-```rust
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-let point = Point { x: 2, y: 3 };
-
-match point {
-    Point { x, .. } => println!("x is {}", x),
-}
-```
-
-This prints `x is 2`.
-
-You can do this kind of match on any member, not only the first:
-
-```rust
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-let point = Point { x: 2, y: 3 };
-
-match point {
-    Point { y, .. } => println!("y is {}", y),
-}
-```
-
-This prints `y is 3`.
-
-This ‘destructuring’ behavior works on any compound data type, like
-[tuples][tuples] or [enums][enums].
-
-[tuples]: primitive-types.html#tuples
-[enums]: enums.html
-
-# Ignoring bindings
-
-You can use `_` in a pattern to disregard the type and value.
-For example, here’s a `match` against a `Result<T, E>`:
-
-```rust
-# let some_value: Result<i32, &'static str> = Err("There was an error");
-match some_value {
-    Ok(value) => println!("got a value: {}", value),
-    Err(_) => println!("an error occurred"),
-}
-```
-
-In the first arm, we bind the value inside the `Ok` variant to `value`. But
-in the `Err` arm, we use `_` to disregard the specific error, and print
-a general error message.
-
-`_` is valid in any pattern that creates a binding. This can be useful to
-ignore parts of a larger structure:
-
-```rust
-fn coordinate() -> (i32, i32, i32) {
-    // Generate and return some sort of triple tuple.
-# (1, 2, 3)
-}
-
-let (x, _, z) = coordinate();
-```
-
-Here, we bind the first and last element of the tuple to `x` and `z`, but
-ignore the middle element.
-
-It’s worth noting that using `_` never binds the value in the first place,
-which means that the value does not move:
-
-```rust
-let tuple: (u32, String) = (5, String::from("five"));
-
-// Here, tuple is moved, because the String moved:
-let (x, _s) = tuple;
-
-// The next line would give "error: use of partially moved value: `tuple`".
-// println!("Tuple is: {:?}", tuple);
-
-// However,
-
-let tuple = (5, String::from("five"));
-
-// Here, tuple is _not_ moved, as the String was never moved, and u32 is Copy:
-let (x, _) = tuple;
-
-// That means this works:
-println!("Tuple is: {:?}", tuple);
-```
-
-This also means that any temporary variables will be dropped at the end of the
-statement:
-
-```rust
-// Here, the String created will be dropped immediately, as it’s not bound:
-
-let _ = String::from("  hello  ").trim();
-```
-
-You can also use `..` in a pattern to disregard multiple values:
-
-```rust
-enum OptionalTuple {
-    Value(i32, i32, i32),
-    Missing,
-}
-
-let x = OptionalTuple::Value(5, -2, 3);
-
-match x {
-    OptionalTuple::Value(..) => println!("Got a tuple!"),
-    OptionalTuple::Missing => println!("No such luck."),
-}
-```
-
-This prints `Got a tuple!`.
-
-# ref and ref mut
-
-If you want to get a [reference][ref], use the `ref` keyword:
-
-```rust
-let x = 5;
-
-match x {
-    ref r => println!("Got a reference to {}", r),
-}
-```
-
-This prints `Got a reference to 5`.
-
-[ref]: references-and-borrowing.html
-
-Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
-keyword _creates_ a reference, for use in the pattern. If you need a mutable
-reference, `ref mut` will work in the same way:
-
-```rust
-let mut x = 5;
-
-match x {
-    ref mut mr => println!("Got a mutable reference to {}", mr),
-}
-```
-
-# Ranges
-
-You can match a range of values with `...`:
-
-```rust
-let x = 1;
-
-match x {
-    1 ... 5 => println!("one through five"),
-    _ => println!("anything"),
-}
-```
-
-This prints `one through five`.
-
-Ranges are mostly used with integers and `char`s:
-
-```rust
-let x = '💅';
-
-match x {
-    'a' ... 'j' => println!("early letter"),
-    'k' ... 'z' => println!("late letter"),
-    _ => println!("something else"),
-}
-```
-
-This prints `something else`.
-
-# Bindings
-
-You can bind values to names with `@`:
-
-```rust
-let x = 1;
-
-match x {
-    e @ 1 ... 5 => println!("got a range element {}", e),
-    _ => println!("anything"),
-}
-```
-
-This prints `got a range element 1`. This is useful when you want to
-do a complicated match of part of a data structure:
-
-```rust
-#[derive(Debug)]
-struct Person {
-    name: Option<String>,
-}
-
-let name = "Steve".to_string();
-let x: Option<Person> = Some(Person { name: Some(name) });
-match x {
-    Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
-    _ => {}
-}
-```
-
-This prints `Some("Steve")`: we’ve bound the inner `name` to `a`.
-
-If you use `@` with `|`, you need to make sure the name is bound in each part
-of the pattern:
-
-```rust
-let x = 5;
-
-match x {
-    e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
-    _ => println!("anything"),
-}
-```
-
-# Guards
-
-You can introduce ‘match guards’ with `if`:
-
-```rust
-enum OptionalInt {
-    Value(i32),
-    Missing,
-}
-
-let x = OptionalInt::Value(5);
-
-match x {
-    OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
-    OptionalInt::Value(..) => println!("Got an int!"),
-    OptionalInt::Missing => println!("No such luck."),
-}
-```
-
-This prints `Got an int!`.
-
-If you’re using `if` with multiple patterns, the `if` applies to both sides:
-
-```rust
-let x = 4;
-let y = false;
-
-match x {
-    4 | 5 if y => println!("yes"),
-    _ => println!("no"),
-}
-```
-
-This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
-only the `5`. In other words, the precedence of `if` behaves like this:
-
-```text
-(4 | 5) if y => ...
-```
-
-not this:
-
-```text
-4 | (5 if y) => ...
-```
-
-# Mix and Match
-
-Whew! That’s a lot of different ways to match things, and they can all be
-mixed and matched, depending on what you’re doing:
-
-```rust,ignore
-match x {
-    Foo { x: Some(ref name), y: None } => ...
-}
-```
-
-Patterns are very powerful. Make good use of them.
diff --git a/src/doc/book/src/primitive-types.md b/src/doc/book/src/primitive-types.md
deleted file mode 100644 (file)
index 8fd3d17..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-# Primitive Types
-
-The Rust language has a number of types that are considered ‘primitive’. This
-means that they’re built-in to the language. Rust is structured in such a way
-that the standard library also provides a number of useful types built on top
-of these ones, as well, but these are the most primitive.
-
-# Booleans
-
-Rust has a built-in boolean type, named `bool`. It has two values, `true` and `false`:
-
-```rust
-let x = true;
-
-let y: bool = false;
-```
-
-A common use of booleans is in [`if` conditionals][if].
-
-[if]: if.html
-
-You can find more documentation for `bool`s [in the standard library
-documentation][bool].
-
-[bool]: ../std/primitive.bool.html
-
-# `char`
-
-The `char` type represents a single Unicode scalar value. You can create `char`s
-with a single tick: (`'`)
-
-```rust
-let x = 'x';
-let two_hearts = '💕';
-```
-
-Unlike some other languages, this means that Rust’s `char` is not a single byte,
-but four.
-
-You can find more documentation for `char`s [in the standard library
-documentation][char].
-
-[char]: ../std/primitive.char.html
-
-# Numeric types
-
-Rust has a variety of numeric types in a few categories: signed and unsigned,
-fixed and variable, floating-point and integer.
-
-These types consist of two parts: the category, and the size. For example,
-`u16` is an unsigned type with sixteen bits of size. More bits lets you have
-bigger numbers.
-
-If a number literal has nothing to cause its type to be inferred, it defaults:
-
-```rust
-let x = 42; // `x` has type `i32`.
-
-let y = 1.0; // `y` has type `f64`.
-```
-
-Here’s a list of the different numeric types, with links to their documentation
-in the standard library:
-
-* [i8](../std/primitive.i8.html)
-* [i16](../std/primitive.i16.html)
-* [i32](../std/primitive.i32.html)
-* [i64](../std/primitive.i64.html)
-* [u8](../std/primitive.u8.html)
-* [u16](../std/primitive.u16.html)
-* [u32](../std/primitive.u32.html)
-* [u64](../std/primitive.u64.html)
-* [isize](../std/primitive.isize.html)
-* [usize](../std/primitive.usize.html)
-* [f32](../std/primitive.f32.html)
-* [f64](../std/primitive.f64.html)
-
-Let’s go over them by category:
-
-## Signed and Unsigned
-
-Integer types come in two varieties: signed and unsigned. To understand the
-difference, let’s consider a number with four bits of size. A signed, four-bit
-number would let you store numbers from `-8` to `+7`. Signed numbers use
-“two’s complement representation”. An unsigned four bit number, since it does
-not need to store negatives, can store values from `0` to `+15`.
-
-Unsigned types use a `u` for their category, and signed types use `i`. The `i`
-is for ‘integer’. So `u8` is an eight-bit unsigned number, and `i8` is an
-eight-bit signed number.
-
-## Fixed-size types
-
-Fixed-size types have a specific number of bits in their representation. Valid
-bit sizes are `8`, `16`, `32`, and `64`. So, `u32` is an unsigned, 32-bit integer,
-and `i64` is a signed, 64-bit integer.
-
-## Variable-size types
-
-Rust also provides types whose particular size depends on the underlying machine
-architecture. Their range is sufficient to express the size of any collection, so
-these types have ‘size’ as the category. They come in signed and unsigned varieties
-which account for two types: `isize` and `usize`.
-
-## Floating-point types
-
-Rust also has two floating point types: `f32` and `f64`. These correspond to
-IEEE-754 single and double precision numbers.
-
-# Arrays
-
-Like many programming languages, Rust has list types to represent a sequence of
-things. The most basic is the *array*, a fixed-size list of elements of the
-same type. By default, arrays are immutable.
-
-```rust
-let a = [1, 2, 3]; // a: [i32; 3]
-let mut m = [1, 2, 3]; // m: [i32; 3]
-```
-
-Arrays have type `[T; N]`. We’ll talk about this `T` notation [in the generics
-section][generics]. The `N` is a compile-time constant, for the length of the
-array.
-
-There’s a shorthand for initializing each element of an array to the same
-value. In this example, each element of `a` will be initialized to `0`:
-
-```rust
-let a = [0; 20]; // a: [i32; 20]
-```
-
-You can get the number of elements in an array `a` with `a.len()`:
-
-```rust
-let a = [1, 2, 3];
-
-println!("a has {} elements", a.len());
-```
-
-You can access a particular element of an array with *subscript notation*:
-
-```rust
-let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
-
-println!("The second name is: {}", names[1]);
-```
-
-Subscripts start at zero, like in most programming languages, so the first name
-is `names[0]` and the second name is `names[1]`. The above example prints
-`The second name is: Brian`. If you try to use a subscript that is not in the
-array, you will get an error: array access is bounds-checked at run-time. Such
-errant access is the source of many bugs in other systems programming
-languages.
-
-You can find more documentation for `array`s [in the standard library
-documentation][array].
-
-[array]: ../std/primitive.array.html
-
-# Slices
-
-A ‘slice’ is a reference to (or “view” into) another data structure. They are
-useful for allowing safe, efficient access to a portion of an array without
-copying. For example, you might want to reference only one line of a file read
-into memory. By nature, a slice is not created directly, but from an existing
-variable binding. Slices have a defined length, and can be mutable or immutable.
-
-Internally, slices are represented as a pointer to the beginning of the data
-and a length.
-
-## Slicing syntax
-
-You can use a combo of `&` and `[]` to create a slice from various things. The
-`&` indicates that slices are similar to [references], which we will cover in
-detail later in this section. The `[]`s, with a range, let you define the
-length of the slice:
-
-```rust
-let a = [0, 1, 2, 3, 4];
-let complete = &a[..]; // A slice containing all of the elements in `a`.
-let middle = &a[1..4]; // A slice of `a`: only the elements `1`, `2`, and `3`.
-```
-
-Slices have type `&[T]`. We’ll talk about that `T` when we cover
-[generics][generics].
-
-[generics]: generics.html
-
-You can find more documentation for slices [in the standard library
-documentation][slice].
-
-[slice]: ../std/primitive.slice.html
-
-# `str`
-
-Rust’s `str` type is the most primitive string type. As an [unsized type][dst],
-it’s not very useful by itself, but becomes useful when placed behind a
-reference, like `&str`. We'll elaborate further when we cover
-[Strings][strings] and [references].
-
-[dst]: unsized-types.html
-[strings]: strings.html
-[references]: references-and-borrowing.html
-
-You can find more documentation for `str` [in the standard library
-documentation][str].
-
-[str]: ../std/primitive.str.html
-
-# Tuples
-
-A tuple is an ordered list of fixed size. Like this:
-
-```rust
-let x = (1, "hello");
-```
-
-The parentheses and commas form this two-length tuple. Here’s the same code, but
-with the type annotated:
-
-```rust
-let x: (i32, &str) = (1, "hello");
-```
-
-As you can see, the type of a tuple looks like the tuple, but with each
-position having a type name rather than the value. Careful readers will also
-note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
-In systems programming languages, strings are a bit more complex than in other
-languages. For now, read `&str` as a *string slice*, and we’ll learn more
-soon.
-
-You can assign one tuple into another, if they have the same contained types
-and [arity]. Tuples have the same arity when they have the same length.
-
-[arity]: glossary.html#arity
-
-```rust
-let mut x = (1, 2); // x: (i32, i32)
-let y = (2, 3); // y: (i32, i32)
-
-x = y;
-```
-
-You can access the fields in a tuple through a *destructuring let*. Here’s
-an example:
-
-```rust
-let (x, y, z) = (1, 2, 3);
-
-println!("x is {}", x);
-```
-
-Remember [before][let] when I said the left-hand side of a `let` statement was more
-powerful than assigning a binding? Here we are. We can put a pattern on
-the left-hand side of the `let`, and if it matches up to the right-hand side,
-we can assign multiple bindings at once. In this case, `let` “destructures”
-or “breaks up” the tuple, and assigns the bits to three bindings.
-
-[let]: variable-bindings.html
-
-This pattern is very powerful, and we’ll see it repeated more later.
-
-You can disambiguate a single-element tuple from a value in parentheses with a
-comma:
-
-```rust
-(0,); // A single-element tuple.
-(0); // A zero in parentheses.
-```
-
-## Tuple Indexing
-
-You can also access fields of a tuple with indexing syntax:
-
-
-```rust
-let tuple = (1, 2, 3);
-
-let x = tuple.0;
-let y = tuple.1;
-let z = tuple.2;
-
-println!("x is {}", x);
-```
-
-Like array indexing, it starts at zero, but unlike array indexing, it uses a
-`.`, rather than `[]`s.
-
-You can find more documentation for tuples [in the standard library
-documentation][tuple].
-
-[tuple]: ../std/primitive.tuple.html
-
-# Functions
-
-Functions also have a type! They look like this:
-
-```rust
-fn foo(x: i32) -> i32 { x }
-
-let x: fn(i32) -> i32 = foo;
-```
-
-In this case, `x` is a ‘function pointer’ to a function that takes an `i32` and
-returns an `i32`.
diff --git a/src/doc/book/src/procedural-macros.md b/src/doc/book/src/procedural-macros.md
deleted file mode 100644 (file)
index e02b5a6..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-# Procedural Macros (and custom Derive)
-
-As you've seen throughout the rest of the book, Rust provides a mechanism
-called "derive" that lets you implement traits easily. For example,
-
-```rust
-#[derive(Debug)]
-struct Point {
-    x: i32,
-    y: i32,
-}
-```
-
-is a lot simpler than
-
-```rust
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-use std::fmt;
-
-impl fmt::Debug for Point {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y)
-    }
-}
-```
-
-Rust includes several traits that you can derive, but it also lets you define
-your own. We can accomplish this task through a feature of Rust called
-"procedural macros." Eventually, procedural macros will allow for all sorts of
-advanced metaprogramming in Rust, but today, they're only for custom derive.
-
-Let's build a very simple trait, and derive it with custom derive.
-
-## Hello World
-
-So the first thing we need to do is start a new crate for our project.
-
-```bash
-$ cargo new --bin hello-world
-```
-
-All we want is to be able to call `hello_world()` on a derived type. Something
-like this:
-
-```rust,ignore
-#[derive(HelloWorld)]
-struct Pancakes;
-
-fn main() {
-    Pancakes::hello_world();
-}
-```
-
-With some kind of nice output, like `Hello, World! My name is Pancakes.`. 
-
-Let's go ahead and write up what we think our macro will look like from a user
-perspective. In `src/main.rs` we write:
-
-```rust,ignore
-#[macro_use]
-extern crate hello_world_derive;
-
-trait HelloWorld {
-    fn hello_world();
-}
-
-#[derive(HelloWorld)]
-struct FrenchToast;
-
-#[derive(HelloWorld)]
-struct Waffles;
-
-fn main() {
-    FrenchToast::hello_world();
-    Waffles::hello_world();
-}
-```
-
-Great. So now we just need to actually write the procedural macro. At the
-moment, procedural macros need to be in their own crate. Eventually, this
-restriction may be lifted, but for now, it's required. As such, there's a
-convention; for a crate named `foo`, a custom derive procedural macro is called
-`foo-derive`. Let's start a new crate called `hello-world-derive` inside our
-`hello-world` project.
-
-```bash
-$ cargo new hello-world-derive
-```
-
-To make sure that our `hello-world` crate is able to find this new crate we've
-created, we'll add it to our toml:
-
-```toml
-[dependencies]
-hello-world-derive = { path = "hello-world-derive" }
-```
-
-As for the source of our `hello-world-derive` crate, here's an example:
-
-```rust,ignore
-extern crate proc_macro;
-extern crate syn;
-#[macro_use]
-extern crate quote;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_derive(HelloWorld)]
-pub fn hello_world(input: TokenStream) -> TokenStream {
-    // Construct a string representation of the type definition
-    let s = input.to_string();
-    
-    // Parse the string representation
-    let ast = syn::parse_macro_input(&s).unwrap();
-
-    // Build the impl
-    let gen = impl_hello_world(&ast);
-    
-    // Return the generated impl
-    gen.parse().unwrap()
-}
-```
-
-So there is a lot going on here. We have introduced two new crates: [`syn`] and
-[`quote`]. As you may have noticed, `input: TokenSteam` is immediately converted
-to a `String`. This `String` is a string representation of the Rust code for which
-we are deriving `HelloWorld`. At the moment, the only thing you can do with a
-`TokenStream` is convert it to a string. A richer API will exist in the future.
-
-So what we really need is to be able to _parse_ Rust code into something
-usable. This is where `syn` comes to play. `syn` is a crate for parsing Rust
-code. The other crate we've introduced is `quote`. It's essentially the dual of
-`syn` as it will make generating Rust code really easy. We could write this
-stuff on our own, but it's much simpler to use these libraries. Writing a full
-parser for Rust code is no simple task.
-
-[`syn`]: https://crates.io/crates/syn
-[`quote`]: https://crates.io/crates/quote
-
-The comments seem to give us a pretty good idea of our overall strategy. We
-are going to take a `String` of the Rust code for the type we are deriving, parse
-it using `syn`, construct the implementation of `hello_world` (using `quote`),
-then pass it back to Rust compiler.
-
-One last note: you'll see some `unwrap()`s there. If you want to provide an
-error for a procedural macro, then you should `panic!` with the error message.
-In this case, we're keeping it as simple as possible.
-
-Great, so let's write `impl_hello_world(&ast)`.
-
-```rust,ignore
-fn impl_hello_world(ast: &syn::MacroInput) -> quote::Tokens {
-    let name = &ast.ident;
-    quote! {
-        impl HelloWorld for #name {
-            fn hello_world() {
-                println!("Hello, World! My name is {}", stringify!(#name));
-            }
-        }
-    }
-}
-```
-
-So this is where quotes comes in. The `ast` argument is a struct that gives us
-a representation of our type (which can be either a `struct` or an `enum`).
-Check out the [docs](https://docs.rs/syn/0.10.5/syn/struct.MacroInput.html),
-there is some useful information there. We are able to get the name of the
-type using `ast.ident`. The `quote!` macro lets us write up the Rust code
-that we wish to return and convert it into `Tokens`. `quote!` lets us use some
-really cool templating mechanics; we simply write `#name` and `quote!` will
-replace it with the variable named `name`. You can even do some repetition
-similar to regular macros work. You should check out the
-[docs](https://docs.rs/quote) for a good introduction.
-
-So I think that's it. Oh, well, we do need to add dependencies for `syn` and
-`quote` in the `cargo.toml` for `hello-world-derive`.
-
-```toml
-[dependencies]
-syn = "0.10.5"
-quote = "0.3.10"
-```
-
-That should be it. Let's try to compile `hello-world`.
-
-```bash
-error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
- --> hello-world-derive/src/lib.rs:8:3
-  |
-8 | #[proc_macro_derive(HelloWorld)]
-  |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-```
-
-Oh, so it appears that we need to declare that our `hello-world-derive` crate is
-a `proc-macro` crate type. How do we do this? Like this:
-
-```toml
-[lib]
-proc-macro = true
-```
-
-Ok so now, let's compile `hello-world`. Executing `cargo run` now yields:
-
-```bash
-Hello, World! My name is FrenchToast
-Hello, World! My name is Waffles
-```
-
-We've done it!
-
-## Custom Attributes
-
-In some cases it might make sense to allow users some kind of configuration.
-For example, the user might want to overwrite the name that is printed in the `hello_world()` method.
-
-This can be achieved with custom attributes:
-
-```rust,ignore
-#[derive(HelloWorld)]
-#[HelloWorldName = "the best Pancakes"]
-struct Pancakes;
-
-fn main() {
-    Pancakes::hello_world();
-}
-```
-
-If we try to compile this though, the compiler will respond with an error:
-
-```bash
-error: The attribute `HelloWorldName` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-```
-
-The compiler needs to know that we're handling this attribute and to not respond with an error.
-This is done in the `hello-world-derive` crate by adding `attributes` to the `proc_macro_derive` attribute:
-
-```rust,ignore
-#[proc_macro_derive(HelloWorld, attributes(HelloWorldName))]
-pub fn hello_world(input: TokenStream) -> TokenStream 
-```
-
-Multiple attributes can be specified that way.
-
-## Raising Errors
-
-Let's assume that we do not want to accept enums as input to our custom derive method.
-
-This condition can be easily checked with the help of `syn`. 
-But how do we tell the user, that we do not accept enums?
-The idiomatic way to report errors in procedural macros is to panic:
-
-```rust,ignore
-fn impl_hello_world(ast: &syn::MacroInput) -> quote::Tokens {
-    let name = &ast.ident;
-    // Check if derive(HelloWorld) was specified for a struct
-    if let syn::Body::Struct(_) = ast.body {
-        // Yes, this is a struct
-        quote! {
-            impl HelloWorld for #name {
-                fn hello_world() {
-                    println!("Hello, World! My name is {}", stringify!(#name));
-                }
-            }
-        }
-    } else {
-        //Nope. This is an Enum. We cannot handle these!
-       panic!("#[derive(HelloWorld)] is only defined for structs, not for enums!");
-    }
-}
-```
-
-If a user now tries to derive `HelloWorld` from an enum they will be greeted with following, hopefully helpful, error:
-
-```bash
-error: custom derive attribute panicked
-  --> src/main.rs
-   |
-   | #[derive(HelloWorld)]
-   |          ^^^^^^^^^^
-   |
-   = help: message: #[derive(HelloWorld)] is only defined for structs, not for enums!
-```
diff --git a/src/doc/book/src/raw-pointers.md b/src/doc/book/src/raw-pointers.md
deleted file mode 100644 (file)
index 1f75665..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-# Raw Pointers
-
-Rust has a number of different smart pointer types in its standard library, but
-there are two types that are extra-special. Much of Rust’s safety comes from
-compile-time checks, but raw pointers don’t have such guarantees, and are
-[unsafe][unsafe] to use.
-
-`*const T` and `*mut T` are called ‘raw pointers’ in Rust. Sometimes, when
-writing certain kinds of libraries, you’ll need to get around Rust’s safety
-guarantees for some reason. In this case, you can use raw pointers to implement
-your library, while exposing a safe interface for your users. For example, `*`
-pointers are allowed to alias, allowing them to be used to write
-shared-ownership types, and even thread-safe shared memory types (the `Rc<T>`
-and `Arc<T>` types are both implemented entirely in Rust).
-
-Here are some things to remember about raw pointers that are different than
-other pointer types. They:
-
-- are not guaranteed to point to valid memory and are not even
-  guaranteed to be non-NULL (unlike both `Box` and `&`);
-- do not have any automatic clean-up, unlike `Box`, and so require
-  manual resource management;
-- are plain-old-data, that is, they don't move ownership, again unlike
-  `Box`, hence the Rust compiler cannot protect against bugs like
-  use-after-free;
-- lack any form of lifetimes, unlike `&`, and so the compiler cannot
-  reason about dangling pointers; and
-- have no guarantees about aliasing or mutability other than mutation
-  not being allowed directly through a `*const T`.
-
-# Basics
-
-Creating a raw pointer is perfectly safe:
-
-```rust
-let x = 5;
-let raw = &x as *const i32;
-
-let mut y = 10;
-let raw_mut = &mut y as *mut i32;
-```
-
-However, dereferencing one is not. This won’t work:
-
-```rust,ignore
-let x = 5;
-let raw = &x as *const i32;
-
-println!("raw points at {}", *raw);
-```
-
-It gives this error:
-
-```text
-error: dereference of raw pointer requires unsafe function or block [E0133]
-     println!("raw points at {}", *raw);
-                                  ^~~~
-```
-
-When you dereference a raw pointer, you’re taking responsibility that it’s not
-pointing somewhere that would be incorrect. As such, you need `unsafe`:
-
-```rust
-let x = 5;
-let raw = &x as *const i32;
-
-let points_at = unsafe { *raw };
-
-println!("raw points at {}", points_at);
-```
-
-For more operations on raw pointers, see [their API documentation][rawapi].
-
-[unsafe]: unsafe.html
-[rawapi]: ../std/primitive.pointer.html
-
-# FFI
-
-Raw pointers are useful for FFI: Rust’s `*const T` and `*mut T` are similar to
-C’s `const T*` and `T*`, respectively. For more about this use, consult the
-[FFI chapter][ffi].
-
-[ffi]: ffi.html
-
-# References and raw pointers
-
-At runtime, a raw pointer `*` and a reference pointing to the same piece of
-data have an identical representation. In fact, an `&T` reference will
-implicitly coerce to an `*const T` raw pointer in safe code and similarly for
-the `mut` variants (both coercions can be performed explicitly with,
-respectively, `value as *const T` and `value as *mut T`).
-
-Going the opposite direction, from `*const` to a reference `&`, is not safe. A
-`&T` is always valid, and so, at a minimum, the raw pointer `*const T` has to
-point to a valid instance of type `T`. Furthermore, the resulting pointer must
-satisfy the aliasing and mutability laws of references. The compiler assumes
-these properties are true for any references, no matter how they are created,
-and so any conversion from raw pointers is asserting that they hold. The
-programmer *must* guarantee this.
-
-The recommended method for the conversion is:
-
-```rust
-// Explicit cast:
-let i: u32 = 1;
-let p_imm: *const u32 = &i as *const u32;
-
-// Implicit coercion:
-let mut m: u32 = 2;
-let p_mut: *mut u32 = &mut m;
-
-unsafe {
-    let ref_imm: &u32 = &*p_imm;
-    let ref_mut: &mut u32 = &mut *p_mut;
-}
-```
-
-The `&*x` dereferencing style is preferred to using a `transmute`. The latter
-is far more powerful than necessary, and the more restricted operation is
-harder to use incorrectly; for example, it requires that `x` is a pointer
-(unlike `transmute`).
diff --git a/src/doc/book/src/references-and-borrowing.md b/src/doc/book/src/references-and-borrowing.md
deleted file mode 100644 (file)
index f01aa45..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-# References and Borrowing
-
-This is the second of three sections presenting Rust’s ownership system. This is one of
-Rust’s most distinct and compelling features, with which Rust developers should
-become quite acquainted. Ownership is how Rust achieves its largest goal,
-memory safety. There are a few distinct concepts, each with its own
-chapter:
-
-* [ownership][ownership], the key concept
-* borrowing, which you’re reading now
-* [lifetimes][lifetimes], an advanced concept of borrowing
-
-These three chapters are related, and in order. You’ll need all three to fully
-understand the ownership system.
-
-[ownership]: ownership.html
-[lifetimes]: lifetimes.html
-
-# Meta
-
-Before we get to the details, two important notes about the ownership system.
-
-Rust has a focus on safety and speed. It accomplishes these goals through many
-‘zero-cost abstractions’, which means that in Rust, abstractions cost as little
-as possible in order to make them work. The ownership system is a prime example
-of a zero-cost abstraction. All of the analysis we’ll talk about in this guide
-is _done at compile time_. You do not pay any run-time cost for any of these
-features.
-
-However, this system does have a certain cost: learning curve. Many new users
-to Rust experience something we like to call ‘fighting with the borrow
-checker’, where the Rust compiler refuses to compile a program that the author
-thinks is valid. This often happens because the programmer’s mental model of
-how ownership should work doesn’t match the actual rules that Rust implements.
-You probably will experience similar things at first. There is good news,
-however: more experienced Rust developers report that once they work with the
-rules of the ownership system for a period of time, they fight the borrow
-checker less and less.
-
-With that in mind, let’s learn about borrowing.
-
-# Borrowing
-
-At the end of the [ownership][ownership] section, we had a nasty function that looked
-like this:
-
-```rust
-fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
-    // Do stuff with `v1` and `v2`.
-
-    // Hand back ownership, and the result of our function.
-    (v1, v2, 42)
-}
-
-let v1 = vec![1, 2, 3];
-let v2 = vec![1, 2, 3];
-
-let (v1, v2, answer) = foo(v1, v2);
-```
-
-This is not idiomatic Rust, however, as it doesn’t take advantage of borrowing. Here’s
-the first step:
-
-```rust
-fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
-    // Do stuff with `v1` and `v2`.
-
-    // Return the answer.
-    42
-}
-
-let v1 = vec![1, 2, 3];
-let v2 = vec![1, 2, 3];
-
-let answer = foo(&v1, &v2);
-
-// We can use `v1` and `v2` here!
-```
-
-A more concrete example:
-
-```rust
-fn main() {
-    // Don't worry if you don't understand how `fold` works, the point here is that an immutable reference is borrowed.
-    fn sum_vec(v: &Vec<i32>) -> i32 {
-        return v.iter().fold(0, |a, &b| a + b);
-    }
-    // Borrow two vectors and sum them.
-    // This kind of borrowing does not allow mutation through the borrowed reference.
-    fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
-        // Do stuff with `v1` and `v2`.
-        let s1 = sum_vec(v1);
-        let s2 = sum_vec(v2);
-        // Return the answer.
-        s1 + s2
-    }
-
-    let v1 = vec![1, 2, 3];
-    let v2 = vec![4, 5, 6];
-
-    let answer = foo(&v1, &v2);
-    println!("{}", answer);
-}
-```
-
-Instead of taking `Vec<i32>`s as our arguments, we take a reference:
-`&Vec<i32>`. And instead of passing `v1` and `v2` directly, we pass `&v1` and
-`&v2`. We call the `&T` type a ‘reference’, and rather than owning the resource,
-it borrows ownership. A binding that borrows something does not deallocate the
-resource when it goes out of scope. This means that after the call to `foo()`,
-we can use our original bindings again.
-
-References are immutable, like bindings. This means that inside of `foo()`,
-the vectors can’t be changed at all:
-
-```rust,ignore
-fn foo(v: &Vec<i32>) {
-     v.push(5);
-}
-
-let v = vec![];
-
-foo(&v);
-```
-
-will give us this error:
-
-```text
-error: cannot borrow immutable borrowed content `*v` as mutable
-v.push(5);
-^
-```
-
-Pushing a value mutates the vector, and so we aren’t allowed to do it.
-
-# &mut references
-
-There’s a second kind of reference: `&mut T`. A ‘mutable reference’ allows you
-to mutate the resource you’re borrowing. For example:
-
-```rust
-let mut x = 5;
-{
-    let y = &mut x;
-    *y += 1;
-}
-println!("{}", x);
-```
-
-This will print `6`. We make `y` a mutable reference to `x`, then add one to
-the thing `y` points at. You’ll notice that `x` had to be marked `mut` as well.
-If it wasn’t, we couldn’t take a mutable borrow to an immutable value.
-
-You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`,
-this is because `y` is a `&mut` reference. You'll need to use asterisks to
-access the contents of a reference as well.
-
-Otherwise, `&mut` references are like references. There _is_ a large
-difference between the two, and how they interact, though. You can tell
-something is fishy in the above example, because we need that extra scope, with
-the `{` and `}`. If we remove them, we get an error:
-
-```text
-error: cannot borrow `x` as immutable because it is also borrowed as mutable
-    println!("{}", x);
-                   ^
-note: previous borrow of `x` occurs here; the mutable borrow prevents
-subsequent moves, borrows, or modification of `x` until the borrow ends
-        let y = &mut x;
-                     ^
-note: previous borrow ends here
-fn main() {
-
-}
-^
-```
-
-As it turns out, there are rules.
-
-# The Rules
-
-Here are the rules for borrowing in Rust:
-
-First, any borrow must last for a scope no greater than that of the owner.
-Second, you may have one or the other of these two kinds of borrows, but not
-both at the same time:
-
-* one or more references (`&T`) to a resource,
-* exactly one mutable reference (`&mut T`).
-
-
-You may notice that this is very similar to, though not exactly the same as,
-the definition of a data race:
-
-> There is a ‘data race’ when two or more pointers access the same memory
-> location at the same time, where at least one of them is writing, and the
-> operations are not synchronized.
-
-With references, you may have as many as you’d like, since none of them are
-writing. However, as we can only have one `&mut` at a time, it is impossible to
-have a data race. This is how Rust prevents data races at compile time: we’ll
-get errors if we break the rules.
-
-With this in mind, let’s consider our example again.
-
-## Thinking in scopes
-
-Here’s the code:
-
-```rust,ignore
-fn main() {
-    let mut x = 5;
-    let y = &mut x;
-
-    *y += 1;
-
-    println!("{}", x);
-}
-```
-
-This code gives us this error:
-
-```text
-error: cannot borrow `x` as immutable because it is also borrowed as mutable
-    println!("{}", x);
-                   ^
-```
-
-This is because we’ve violated the rules: we have a `&mut T` pointing to `x`,
-and so we aren’t allowed to create any `&T`s. It's one or the other. The note
-hints at how to think about this problem:
-
-```text
-note: previous borrow ends here
-fn main() {
-
-}
-^
-```
-
-In other words, the mutable borrow is held through the rest of our example. What
-we want is for the mutable borrow by `y` to end so that the resource can be
-returned to the owner, `x`. `x` can then provide an immutable borrow to `println!`.
-In Rust, borrowing is tied to the scope that the borrow is valid for. And our
-scopes look like this:
-
-```rust,ignore
-fn main() {
-    let mut x = 5;
-
-    let y = &mut x;    // -+ &mut borrow of `x` starts here.
-                       //  |
-    *y += 1;           //  |
-                       //  |
-    println!("{}", x); // -+ - Try to borrow `x` here.
-}                      // -+ &mut borrow of `x` ends here.
-                       
-```
-
-The scopes conflict: we can’t make an `&x` while `y` is in scope.
-
-So when we add the curly braces:
-
-```rust
-let mut x = 5;
-
-{
-    let y = &mut x; // -+ &mut borrow starts here.
-    *y += 1;        //  |
-}                   // -+ ... and ends here.
-
-println!("{}", x);  // <- Try to borrow `x` here.
-```
-
-There’s no problem. Our mutable borrow goes out of scope before we create an
-immutable one. So scope is the key to seeing how long a borrow lasts for.
-
-## Issues borrowing prevents
-
-Why have these restrictive rules? Well, as we noted, these rules prevent data
-races. What kinds of issues do data races cause? Here are a few.
-
-### Iterator invalidation
-
-One example is ‘iterator invalidation’, which happens when you try to mutate a
-collection that you’re iterating over. Rust’s borrow checker prevents this from
-happening:
-
-```rust
-let mut v = vec![1, 2, 3];
-
-for i in &v {
-    println!("{}", i);
-}
-```
-
-This prints out one through three. As we iterate through the vector, we’re
-only given references to the elements. And `v` is itself borrowed as immutable,
-which means we can’t change it while we’re iterating:
-
-```rust,ignore
-let mut v = vec![1, 2, 3];
-
-for i in &v {
-    println!("{}", i);
-    v.push(34);
-}
-```
-
-Here’s the error:
-
-```text
-error: cannot borrow `v` as mutable because it is also borrowed as immutable
-    v.push(34);
-    ^
-note: previous borrow of `v` occurs here; the immutable borrow prevents
-subsequent moves or mutable borrows of `v` until the borrow ends
-for i in &v {
-          ^
-note: previous borrow ends here
-for i in &v {
-    println!(“{}”, i);
-    v.push(34);
-}
-^
-```
-
-We can’t modify `v` because it’s borrowed by the loop.
-
-### Use after free
-
-References must not live longer than the resource they refer to. Rust will
-check the scopes of your references to ensure that this is true.
-
-If Rust didn’t check this property, we could accidentally use a reference
-which was invalid. For example:
-
-```rust,ignore
-let y: &i32;
-{
-    let x = 5;
-    y = &x;
-}
-
-println!("{}", y);
-```
-
-We get this error:
-
-```text
-error: `x` does not live long enough
-    y = &x;
-         ^
-note: reference must be valid for the block suffix following statement 0 at
-2:16...
-let y: &i32;
-{
-    let x = 5;
-    y = &x;
-}
-
-note: ...but borrowed value is only valid for the block suffix following
-statement 0 at 4:18
-    let x = 5;
-    y = &x;
-}
-```
-
-In other words, `y` is only valid for the scope where `x` exists. As soon as
-`x` goes away, it becomes invalid to refer to it. As such, the error says that
-the borrow ‘doesn’t live long enough’ because it’s not valid for the right
-amount of time.
-
-The same problem occurs when the reference is declared _before_ the variable it
-refers to. This is because resources within the same scope are freed in the
-opposite order they were declared:
-
-```rust,ignore
-let y: &i32;
-let x = 5;
-y = &x;
-
-println!("{}", y);
-```
-
-We get this error:
-
-```text
-error: `x` does not live long enough
-y = &x;
-     ^
-note: reference must be valid for the block suffix following statement 0 at
-2:16...
-    let y: &i32;
-    let x = 5;
-    y = &x;
-
-    println!("{}", y);
-}
-
-note: ...but borrowed value is only valid for the block suffix following
-statement 1 at 3:14
-    let x = 5;
-    y = &x;
-
-    println!("{}", y);
-}
-```
-
-In the above example, `y` is declared before `x`, meaning that `y` lives longer
-than `x`, which is not allowed.
diff --git a/src/doc/book/src/release-channels.md b/src/doc/book/src/release-channels.md
deleted file mode 100644 (file)
index af89ca8..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-# Release Channels
-
-The Rust project uses a concept called ‘release channels’ to manage releases.
-It’s important to understand this process to choose which version of Rust
-your project should use.
-
-# Overview
-
-There are three channels for Rust releases:
-
-* Nightly
-* Beta
-* Stable
-
-New nightly releases are created once a day. Every six weeks, the latest
-nightly release is promoted to ‘Beta’. At that point, it will only receive
-patches to fix serious errors. Six weeks later, the beta is promoted to
-‘Stable’, and becomes the next release of `1.x`.
-
-This process happens in parallel. So every six weeks, on the same day,
-nightly goes to beta, beta goes to stable. When `1.x` is released, at
-the same time, `1.(x + 1)-beta` is released, and the nightly becomes the
-first version of `1.(x + 2)-nightly`.
-
-# Choosing a version
-
-Generally speaking, unless you have a specific reason, you should be using the
-stable release channel. These releases are intended for a general audience.
-
-However, depending on your interest in Rust, you may choose to use nightly
-instead. The basic tradeoff is this: in the nightly channel, you can use
-unstable, new Rust features. However, unstable features are subject to change,
-and so any new nightly release may break your code. If you use the stable
-release, you cannot use experimental features, but the next release of Rust
-will not cause significant issues through breaking changes.
-
-# Helping the ecosystem through CI
-
-What about beta? We encourage all Rust users who use the stable release channel
-to also test against the beta channel in their continuous integration systems.
-This will help alert the team in case there’s an accidental regression.
-
-Additionally, testing against nightly can catch regressions even sooner, and so
-if you don’t mind a third build, we’d appreciate testing against all channels.
-
-As an example, many Rust programmers use [Travis](https://travis-ci.org/) to
-test their crates, which is free for open source projects. Travis [supports
-Rust directly][travis], and you can use a `.travis.yml` file like this to
-test on all channels:
-
-```yaml
-language: rust
-rust:
-  - nightly
-  - beta
-  - stable
-
-matrix:
-  allow_failures:
-    - rust: nightly
-```
-
-[travis]: http://docs.travis-ci.com/user/languages/rust/
-
-With this configuration, Travis will test all three channels, but if something
-breaks on nightly, it won’t fail your build. A similar configuration is
-recommended for any CI system, check the documentation of the one you’re
-using for more details.
diff --git a/src/doc/book/src/strings.md b/src/doc/book/src/strings.md
deleted file mode 100644 (file)
index ffc9d2b..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-# Strings
-
-Strings are an important concept for any programmer to master. Rust’s string
-handling system is a bit different from other languages, due to its systems
-focus. Any time you have a data structure of variable size, things can get
-tricky, and strings are a re-sizable data structure. That being said, Rust’s
-strings also work differently than in some other systems languages, such as C.
-
-Let’s dig into the details. A ‘string’ is a sequence of Unicode scalar values
-encoded as a stream of UTF-8 bytes. All strings are guaranteed to be a valid
-encoding of UTF-8 sequences. Additionally, unlike some systems languages,
-strings are not NUL-terminated and can contain NUL bytes.
-
-Rust has two main types of strings: `&str` and `String`. Let’s talk about
-`&str` first. These are called ‘string slices’. A string slice has a fixed
-size, and cannot be mutated. It is a reference to a sequence of UTF-8 bytes.
-
-```rust
-let greeting = "Hello there."; // greeting: &'static str
-```
-
-`"Hello there."` is a string literal and its type is `&'static str`. A string
-literal is a string slice that is statically allocated, meaning that it’s saved
-inside our compiled program, and exists for the entire duration it runs. The
-`greeting` binding is a reference to this statically allocated string. Any
-function expecting a string slice will also accept a string literal.
-
-String literals can span multiple lines. There are two forms. The first will
-include the newline and the leading spaces:
-
-```rust
-let s = "foo
-    bar";
-
-assert_eq!("foo\n    bar", s);
-```
-
-The second, with a `\`, trims the spaces and the newline:
-
-```rust
-let s = "foo\
-    bar";
-
-assert_eq!("foobar", s);
-```
-
-Note that you normally cannot access a `str` directly, but only through a `&str`
-reference. This is because `str` is an unsized type which requires additional
-runtime information to be usable. For more information see the chapter on
-[unsized types][ut].
-
-Rust has more than only `&str`s though. A `String` is a heap-allocated string.
-This string is growable, and is also guaranteed to be UTF-8. `String`s are
-commonly created by converting from a string slice using the `to_string`
-method.
-
-```rust
-let mut s = "Hello".to_string(); // mut s: String
-println!("{}", s);
-
-s.push_str(", world.");
-println!("{}", s);
-```
-
-`String`s will coerce into `&str` with an `&`:
-
-```rust
-fn takes_slice(slice: &str) {
-    println!("Got: {}", slice);
-}
-
-fn main() {
-    let s = "Hello".to_string();
-    takes_slice(&s);
-}
-```
-
-This coercion does not happen for functions that accept one of `&str`’s traits
-instead of `&str`. For example, [`TcpStream::connect`][connect] has a parameter
-of type `ToSocketAddrs`. A `&str` is okay but a `String` must be explicitly
-converted using `&*`.
-
-```rust,no_run
-use std::net::TcpStream;
-
-TcpStream::connect("192.168.0.1:3000"); // Parameter is of type &str.
-
-let addr_string = "192.168.0.1:3000".to_string();
-TcpStream::connect(&*addr_string); // Convert `addr_string` to &str.
-```
-
-Viewing a `String` as a `&str` is cheap, but converting the `&str` to a
-`String` involves allocating memory. No reason to do that unless you have to!
-
-## Indexing
-
-Because strings are valid UTF-8, they do not support indexing:
-
-```rust,ignore
-let s = "hello";
-
-println!("The first letter of s is {}", s[0]); // ERROR!!!
-```
-
-Usually, access to a vector with `[]` is very fast. But, because each character
-in a UTF-8 encoded string can be multiple bytes, you have to walk over the
-string to find the nᵗʰ letter of a string. This is a significantly more
-expensive operation, and we don’t want to be misleading. Furthermore, ‘letter’
-isn’t something defined in Unicode, exactly. We can choose to look at a string as
-individual bytes, or as codepoints:
-
-```rust
-let hachiko = "忠犬ハチ公";
-
-for b in hachiko.as_bytes() {
-    print!("{}, ", b);
-}
-
-println!("");
-
-for c in hachiko.chars() {
-    print!("{}, ", c);
-}
-
-println!("");
-```
-
-This prints:
-
-```text
-229, 191, 160, 231, 138, 172, 227, 131, 143, 227, 131, 129, 229, 133, 172,
-忠, 犬, ハ, チ, 公,
-```
-
-As you can see, there are more bytes than `char`s.
-
-You can get something similar to an index like this:
-
-```rust
-# let hachiko = "忠犬ハチ公";
-let dog = hachiko.chars().nth(1); // Kinda like `hachiko[1]`.
-```
-
-This emphasizes that we have to walk from the beginning of the list of `chars`.
-
-## Slicing
-
-You can get a slice of a string with the slicing syntax:
-
-```rust
-let dog = "hachiko";
-let hachi = &dog[0..5];
-```
-
-But note that these are _byte_ offsets, not _character_ offsets. So
-this will fail at runtime:
-
-```rust,should_panic
-let dog = "忠犬ハチ公";
-let hachi = &dog[0..2];
-```
-
-with this error:
-
-```text
-thread 'main' panicked at 'byte index 2 is not a char boundary; it is inside '忠'
-(bytes 0..3) of `忠犬ハチ公`'
-```
-
-## Concatenation
-
-If you have a `String`, you can concatenate a `&str` to the end of it:
-
-```rust
-let hello = "Hello ".to_string();
-let world = "world!";
-
-let hello_world = hello + world;
-```
-
-But if you have two `String`s, you need an `&`:
-
-```rust
-let hello = "Hello ".to_string();
-let world = "world!".to_string();
-
-let hello_world = hello + &world;
-```
-
-This is because `&String` can automatically coerce to a `&str`. This is a
-feature called ‘[`Deref` coercions][dc]’.
-
-[ut]: unsized-types.html
-[dc]: deref-coercions.html
-[connect]: ../std/net/struct.TcpStream.html#method.connect
diff --git a/src/doc/book/src/structs.md b/src/doc/book/src/structs.md
deleted file mode 100644 (file)
index 3efa4f0..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-# Structs
-
-`struct`s are a way of creating more complex data types. For example, if we were
-doing calculations involving coordinates in 2D space, we would need both an `x`
-and a `y` value:
-
-```rust
-let origin_x = 0;
-let origin_y = 0;
-```
-
-A `struct` lets us combine these two into a single, unified datatype with `x`
-and `y` as field labels:
-
-```rust
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-fn main() {
-    let origin = Point { x: 0, y: 0 }; // origin: Point
-
-    println!("The origin is at ({}, {})", origin.x, origin.y);
-}
-```
-
-There’s a lot going on here, so let’s break it down. We declare a `struct` with
-the `struct` keyword, and then with a name. By convention, `struct`s begin with
-a capital letter and are camel cased: `PointInSpace`, not `Point_In_Space`.
-
-We can create an instance of our `struct` via `let`, as usual, but we use a `key:
-value` style syntax to set each field. The order doesn’t need to be the same as
-in the original declaration.
-
-Finally, because fields have names, we can access them through dot
-notation: `origin.x`.
-
-The values in `struct`s are immutable by default, like other bindings in Rust.
-Use `mut` to make them mutable:
-
-```rust
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-fn main() {
-    let mut point = Point { x: 0, y: 0 };
-
-    point.x = 5;
-
-    println!("The point is at ({}, {})", point.x, point.y);
-}
-```
-
-This will print `The point is at (5, 0)`.
-
-Rust does not support field mutability at the language level, so you cannot
-write something like this:
-
-```rust,ignore
-struct Point {
-    mut x: i32, // This causes an error.
-    y: i32,
-}
-```
-
-Mutability is a property of the binding, not of the structure itself. If you’re
-used to field-level mutability, this may seem strange at first, but it
-significantly simplifies things. It even lets you make things mutable on a temporary
-basis:
-
-```rust,ignore
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-fn main() {
-    let mut point = Point { x: 0, y: 0 };
-
-    point.x = 5;
-
-    let point = point; // `point` is now immutable.
-
-    point.y = 6; // This causes an error.
-}
-```
-
-Your structure can still contain `&mut` references, which will let
-you do some kinds of mutation:
-
-```rust
-struct Point {
-    x: i32,
-    y: i32,
-}
-
-struct PointRef<'a> {
-    x: &'a mut i32,
-    y: &'a mut i32,
-}
-
-fn main() {
-    let mut point = Point { x: 0, y: 0 };
-
-    {
-        let r = PointRef { x: &mut point.x, y: &mut point.y };
-
-        *r.x = 5;
-        *r.y = 6;
-    }
-
-    assert_eq!(5, point.x);
-    assert_eq!(6, point.y);
-}
-```
-
-Initialization of a data structure (struct, enum, union) can be simplified when
-fields of the data structure are initialized with variables of the same
-names as the fields.
-
-```
-#[derive(Debug)]
-struct Person<'a> {
-    name: &'a str,
-    age: u8
-}
-
-fn main() {
-    // Create struct with field init shorthand
-    let name = "Peter";
-    let age = 27;
-    let peter = Person { name, age };
-
-    // Debug-print struct
-    println!("{:?}", peter);
-}
-```
-
-# Update syntax
-
-A `struct` can include `..` to indicate that you want to use a copy of some
-other `struct` for some of the values. For example:
-
-```rust
-struct Point3d {
-    x: i32,
-    y: i32,
-    z: i32,
-}
-
-let mut point = Point3d { x: 0, y: 0, z: 0 };
-point = Point3d { y: 1, .. point };
-```
-
-This gives `point` a new `y`, but keeps the old `x` and `z` values. It doesn’t
-have to be the same `struct` either, you can use this syntax when making new
-ones, and it will copy the values you don’t specify:
-
-```rust
-# struct Point3d {
-#     x: i32,
-#     y: i32,
-#     z: i32,
-# }
-let origin = Point3d { x: 0, y: 0, z: 0 };
-let point = Point3d { z: 1, x: 2, .. origin };
-```
-
-# Tuple structs
-
-Rust has another data type that’s like a hybrid between a [tuple][tuple] and a
-`struct`, called a ‘tuple struct’. Tuple structs have a name, but their fields
-don't. They are declared with the `struct` keyword, and then with a name
-followed by a tuple:
-
-[tuple]: primitive-types.html#tuples
-
-```rust
-struct Color(i32, i32, i32);
-struct Point(i32, i32, i32);
-
-let black = Color(0, 0, 0);
-let origin = Point(0, 0, 0);
-```
-
-Here, `black` and `origin` are not the same type, even though they contain the
-same values.
-
-The members of a tuple struct may be accessed by dot notation or destructuring
-`let`, just like regular tuples:
-
-```rust
-# struct Color(i32, i32, i32);
-# struct Point(i32, i32, i32);
-# let black = Color(0, 0, 0);
-# let origin = Point(0, 0, 0);
-let black_r = black.0;
-let Point(_, origin_y, origin_z) = origin;
-```
-
-Patterns like `Point(_, origin_y, origin_z)` are also used in
-[match expressions][match].
-
-One case when a tuple struct is very useful is when it has only one element.
-We call this the ‘newtype’ pattern, because it allows you to create a new type
-that is distinct from its contained value and also expresses its own semantic
-meaning:
-
-```rust
-struct Inches(i32);
-
-let length = Inches(10);
-
-let Inches(integer_length) = length;
-println!("length is {} inches", integer_length);
-```
-
-As above, you can extract the inner integer type through a destructuring `let`.
-In this case, the `let Inches(integer_length)` assigns `10` to `integer_length`.
-We could have used dot notation to do the same thing:
-
-```rust
-# struct Inches(i32);
-# let length = Inches(10);
-let integer_length = length.0;
-```
-
-It's always possible to use a `struct` instead of a tuple struct, and can be
-clearer. We could write `Color` and `Point` like this instead:
-
-```rust
-struct Color {
-    red: i32,
-    blue: i32,
-    green: i32,
-}
-
-struct Point {
-    x: i32,
-    y: i32,
-    z: i32,
-}
-```
-
-Good names are important, and while values in a tuple struct can be
-referenced with dot notation as well, a `struct` gives us actual names,
-rather than positions.
-
-[match]: match.html
-
-# Unit-like structs
-
-You can define a `struct` with no members at all:
-
-```rust,compile_fail,E0423
-struct Electron {} // Use empty braces...
-struct Proton;     // ...or just a semicolon.
-
-// Use the same notation when creating an instance.
-let x = Electron {};
-let y = Proton;
-let z = Electron; // Error
-```
-
-Such a `struct` is called ‘unit-like’ because it resembles the empty
-tuple, `()`, sometimes called ‘unit’. Like a tuple struct, it defines a
-new type.
-
-This is rarely useful on its own (although sometimes it can serve as a
-marker type), but in combination with other features, it can become
-useful. For instance, a library may ask you to create a structure that
-implements a certain [trait][trait] to handle events. If you don’t have
-any data you need to store in the structure, you can create a
-unit-like `struct`.
-
-[trait]: traits.html
diff --git a/src/doc/book/src/syntax-and-semantics.md b/src/doc/book/src/syntax-and-semantics.md
deleted file mode 100644 (file)
index aa4c125..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# Syntax and Semantics
-
-This chapter breaks Rust down into small chunks, one for each concept.
-
-If you’d like to learn Rust from the bottom up, reading this in order is a
-great way to do that.
-
-These sections also form a reference for each concept, so if you’re reading
-another tutorial and find something confusing, you can find it explained
-somewhere in here.
diff --git a/src/doc/book/src/syntax-index.md b/src/doc/book/src/syntax-index.md
deleted file mode 100644 (file)
index a06520f..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-# Syntax Index
-
-## Keywords
-
-* `as`: primitive casting, or disambiguating the specific trait containing an item.  See [Casting Between Types (`as`)], [Universal Function Call Syntax (Angle-bracket Form)], [Associated Types].
-* `break`: break out of loop.  See [Loops (Ending Iteration Early)].
-* `const`: constant items and constant raw pointers.  See [`const` and `static`], [Raw Pointers].
-* `continue`: continue to next loop iteration.  See [Loops (Ending Iteration Early)].
-* `crate`: external crate linkage.  See [Crates and Modules (Importing External Crates)].
-* `else`: fallback for `if` and `if let` constructs.  See [`if`], [`if let`].
-* `enum`: defining enumeration.  See [Enums].
-* `extern`: external crate, function, and variable linkage.  See [Crates and Modules (Importing External Crates)], [Foreign Function Interface].
-* `false`: boolean false literal.  See [Primitive Types (Booleans)].
-* `fn`: function definition and function pointer types.  See [Functions].
-* `for`: iterator loop, part of trait `impl` syntax, and higher-ranked lifetime syntax.  See [Loops (`for`)], [Method Syntax].
-* `if`: conditional branching.  See [`if`], [`if let`].
-* `impl`: inherent and trait implementation blocks.  See [Method Syntax].
-* `in`: part of `for` loop syntax.  See [Loops (`for`)].
-* `let`: variable binding.  See [Variable Bindings].
-* `loop`: unconditional, infinite loop.  See [Loops (`loop`)].
-* `match`: pattern matching.  See [Match].
-* `mod`: module declaration.  See [Crates and Modules (Defining Modules)].
-* `move`: part of closure syntax.  See [Closures (`move` closures)].
-* `mut`: denotes mutability in pointer types and pattern bindings.  See [Mutability].
-* `pub`: denotes public visibility in `struct` fields, `impl` blocks, and modules.  See [Crates and Modules (Exporting a Public Interface)].
-* `ref`: by-reference binding.  See [Patterns (`ref` and `ref mut`)].
-* `return`: return from function.  See [Functions (Early Returns)].
-* `Self`: implementor type alias.  See [Traits].
-* `self`: method subject.  See [Method Syntax (Method Calls)].
-* `static`: global variable.  See [`const` and `static` (`static`)].
-* `struct`: structure definition.  See [Structs].
-* `trait`: trait definition.  See [Traits].
-* `true`: boolean true literal.  See [Primitive Types (Booleans)].
-* `type`: type alias, and associated type definition.  See [`type` Aliases], [Associated Types].
-* `unsafe`: denotes unsafe code, functions, traits, and implementations.  See [Unsafe].
-* `use`: import symbols into scope.  See [Crates and Modules (Importing Modules with `use`)].
-* `where`: type constraint clauses.  See [Traits (`where` clause)].
-* `while`: conditional loop.  See [Loops (`while`)].
-
-## Operators and Symbols
-
-* `!` (`ident!(…)`, `ident!{…}`, `ident![…]`): denotes macro expansion.  See [Macros].
-* `!` (`!expr`): bitwise or logical complement.  Overloadable (`Not`).
-* `!=` (`var != expr`): nonequality comparison.  Overloadable (`PartialEq`).
-* `%` (`expr % expr`): arithmetic remainder.  Overloadable (`Rem`).
-* `%=` (`var %= expr`): arithmetic remainder & assignment. Overloadable (`RemAssign`).
-* `&` (`expr & expr`): bitwise and.  Overloadable (`BitAnd`).
-* `&` (`&expr`, `&mut expr`): borrow.  See [References and Borrowing].
-* `&` (`&type`, `&mut type`, `&'a type`, `&'a mut type`): borrowed pointer type.  See [References and Borrowing].
-* `&=` (`var &= expr`): bitwise and & assignment. Overloadable (`BitAndAssign`).
-* `&&` (`expr && expr`): logical and.
-* `*` (`expr * expr`): arithmetic multiplication.  Overloadable (`Mul`).
-* `*` (`*expr`): dereference.
-* `*` (`*const type`, `*mut type`): raw pointer.  See [Raw Pointers].
-* `*=` (`var *= expr`): arithmetic multiplication & assignment. Overloadable (`MulAssign`).
-* `+` (`expr + expr`): arithmetic addition.  Overloadable (`Add`).
-* `+` (`trait + trait`, `'a + trait`): compound type constraint.  See [Traits (Multiple Trait Bounds)].
-* `+=` (`var += expr`): arithmetic addition & assignment. Overloadable (`AddAssign`).
-* `,`: argument and element separator.  See [Attributes], [Functions], [Structs], [Generics], [Match], [Closures], [Crates and Modules (Importing Modules with `use`)].
-* `-` (`expr - expr`): arithmetic subtraction.  Overloadable (`Sub`).
-* `-` (`- expr`): arithmetic negation.  Overloadable (`Neg`).
-* `-=` (`var -= expr`): arithmetic subtraction & assignment. Overloadable (`SubAssign`).
-* `->` (`fn(…) -> type`, `|…| -> type`): function and closure return type.  See [Functions], [Closures].
-* `.` (`expr.ident`): member access.  See [Structs], [Method Syntax].
-* `..` (`..`, `expr..`, `..expr`, `expr..expr`): right-exclusive range literal.
-* `..` (`..expr`): struct literal update syntax.  See [Structs (Update syntax)].
-* `..` (`variant(x, ..)`, `struct_type { x, .. }`): "and the rest" pattern binding.  See [Patterns (Ignoring bindings)].
-* `...` (`...expr`, `expr...expr`) *in an expression*: inclusive range expression. See [Iterators].
-* `...` (`expr...expr`) *in a pattern*: inclusive range pattern.  See [Patterns (Ranges)].
-* `/` (`expr / expr`): arithmetic division.  Overloadable (`Div`).
-* `/=` (`var /= expr`): arithmetic division & assignment. Overloadable (`DivAssign`).
-* `:` (`pat: type`, `ident: type`): constraints.  See [Variable Bindings], [Functions], [Structs], [Traits].
-* `:` (`ident: expr`): struct field initializer.  See [Structs].
-* `:` (`'a: loop {…}`): loop label.  See [Loops (Loops Labels)].
-* `;`: statement and item terminator.
-* `;` (`[…; len]`): part of fixed-size array syntax.  See [Primitive Types (Arrays)].
-* `<<` (`expr << expr`): left-shift.  Overloadable (`Shl`).
-* `<<=` (`var <<= expr`): left-shift & assignment. Overloadable (`ShlAssign`).
-* `<` (`expr < expr`): less-than comparison.  Overloadable (`PartialOrd`).
-* `<=` (`var <= expr`): less-than or equal-to comparison.  Overloadable (`PartialOrd`).
-* `=` (`var = expr`, `ident = type`): assignment/equivalence.  See [Variable Bindings], [`type` Aliases], generic parameter defaults.
-* `==` (`var == expr`): equality comparison.  Overloadable (`PartialEq`).
-* `=>` (`pat => expr`): part of match arm syntax.  See [Match].
-* `>` (`expr > expr`): greater-than comparison.  Overloadable (`PartialOrd`).
-* `>=` (`var >= expr`): greater-than or equal-to comparison.  Overloadable (`PartialOrd`).
-* `>>` (`expr >> expr`): right-shift.  Overloadable (`Shr`).
-* `>>=` (`var >>= expr`): right-shift & assignment. Overloadable (`ShrAssign`).
-* `@` (`ident @ pat`): pattern binding.  See [Patterns (Bindings)].
-* `^` (`expr ^ expr`): bitwise exclusive or.  Overloadable (`BitXor`).
-* `^=` (`var ^= expr`): bitwise exclusive or & assignment. Overloadable (`BitXorAssign`).
-* `|` (`expr | expr`): bitwise or.  Overloadable (`BitOr`).
-* `|` (`pat | pat`): pattern alternatives.  See [Patterns (Multiple patterns)].
-* `|` (`|…| expr`): closures.  See [Closures].
-* `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`).
-* `||` (`expr || expr`): logical or.
-* `_`: "ignored" pattern binding (see [Patterns (Ignoring bindings)]). Also used to make integer-literals readable (see [Reference (Integer literals)]).
-* `?` (`expr?`): Error propagation. Returns early when `Err(_)` is encountered, unwraps otherwise. Similar to the [`try!` macro].
-
-## Other Syntax
-
-<!-- Various bits of standalone stuff. -->
-
-* `'ident`: named lifetime or loop label.  See [Lifetimes], [Loops (Loops Labels)].
-* `…u8`, `…i32`, `…f64`, `…usize`, …: numeric literal of specific type.
-* `"…"`: string literal.  See [Strings].
-* `r"…"`, `r#"…"#`, `r##"…"##`, …: raw string literal, escape characters are not processed. See [Reference (Raw String Literals)].
-* `b"…"`: byte string literal, constructs a `[u8]` instead of a string. See [Reference (Byte String Literals)].
-* `br"…"`, `br#"…"#`, `br##"…"##`, …: raw byte string literal, combination of raw and byte string literal. See [Reference (Raw Byte String Literals)].
-* `'…'`: character literal.  See [Primitive Types (`char`)].
-* `b'…'`: ASCII byte literal.
-* `|…| expr`: closure.  See [Closures].
-
-<!-- Path-related syntax -->
-
-* `ident::ident`: path.  See [Crates and Modules (Defining Modules)].
-* `::path`: path relative to the crate root (*i.e.* an explicitly absolute path).  See [Crates and Modules (Re-exporting with `pub use`)].
-* `self::path`: path relative to the current module (*i.e.* an explicitly relative path).  See [Crates and Modules (Re-exporting with `pub use`)].
-* `super::path`: path relative to the parent of the current module.  See [Crates and Modules (Re-exporting with `pub use`)].
-* `type::ident`, `<type as trait>::ident`: associated constants, functions, and types.  See [Associated Types].
-* `<type>::…`: associated item for a type which cannot be directly named (*e.g.* `<&T>::…`, `<[T]>::…`, *etc.*).  See [Associated Types].
-* `trait::method(…)`: disambiguating a method call by naming the trait which defines it. See [Universal Function Call Syntax].
-* `type::method(…)`: disambiguating a method call by naming the type for which it's defined. See [Universal Function Call Syntax].
-* `<type as trait>::method(…)`: disambiguating a method call by naming the trait _and_ type. See [Universal Function Call Syntax (Angle-bracket Form)].
-
-<!-- Generics -->
-
-* `path<…>` (*e.g.* `Vec<u8>`): specifies parameters to generic type *in a type*.  See [Generics].
-* `path::<…>`, `method::<…>` (*e.g.* `"42".parse::<i32>()`): specifies parameters to generic type, function, or method *in an expression*.  See [Generics § Resolving ambiguities](generics.html#resolving-ambiguities).
-* `fn ident<…> …`: define generic function.  See [Generics].
-* `struct ident<…> …`: define generic structure.  See [Generics].
-* `enum ident<…> …`: define generic enumeration.  See [Generics].
-* `impl<…> …`: define generic implementation.
-* `for<…> type`: higher-ranked lifetime bounds.
-* `type<ident=type>` (*e.g.* `Iterator<Item=T>`): a generic type where one or more associated types have specific assignments.  See [Associated Types].
-
-<!-- Constraints -->
-
-* `T: U`: generic parameter `T` constrained to types that implement `U`.  See [Traits].
-* `T: 'a`: generic type `T` must outlive lifetime `'a`. When we say that a type 'outlives' the lifetime, we mean that it cannot transitively contain any references with lifetimes shorter than `'a`.
-* `T : 'static`: The generic type `T` contains no borrowed references other than `'static` ones.
-* `'b: 'a`: generic lifetime `'b` must outlive lifetime `'a`.
-* `T: ?Sized`: allow generic type parameter to be a dynamically-sized type.  See [Unsized Types (`?Sized`)].
-* `'a + trait`, `trait + trait`: compound type constraint.  See [Traits (Multiple Trait Bounds)].
-
-<!-- Macros and attributes -->
-
-* `#[meta]`: outer attribute.  See [Attributes].
-* `#![meta]`: inner attribute.  See [Attributes].
-* `$ident`: macro substitution.  See [Macros].
-* `$ident:kind`: macro capture.  See [Macros].
-* `$(…)…`: macro repetition.  See [Macros].
-
-<!-- Comments -->
-
-* `//`: line comment.  See [Comments].
-* `//!`: inner line doc comment.  See [Comments].
-* `///`: outer line doc comment.  See [Comments].
-* `/*…*/`: block comment.  See [Comments].
-* `/*!…*/`: inner block doc comment.  See [Comments].
-* `/**…*/`: outer block doc comment.  See [Comments].
-
-<!-- Special types -->
-
-* `!`: always empty Never type.  See [Diverging Functions].
-
-<!-- Various things involving parens and tuples -->
-
-* `()`: empty tuple (*a.k.a.* unit), both literal and type.
-* `(expr)`: parenthesized expression.
-* `(expr,)`: single-element tuple expression.  See [Primitive Types (Tuples)].
-* `(type,)`: single-element tuple type.  See [Primitive Types (Tuples)].
-* `(expr, …)`: tuple expression.  See [Primitive Types (Tuples)].
-* `(type, …)`: tuple type.  See [Primitive Types (Tuples)].
-* `expr(expr, …)`: function call expression.  Also used to initialize tuple `struct`s and tuple `enum` variants.  See [Functions].
-* `ident!(…)`, `ident!{…}`, `ident![…]`: macro invocation.  See [Macros].
-* `expr.0`, `expr.1`, …: tuple indexing.  See [Primitive Types (Tuple Indexing)].
-
-<!-- Bracey things -->
-
-* `{…}`: block expression.
-* `Type {…}`: `struct` literal.  See [Structs].
-
-<!-- Brackety things -->
-
-* `[…]`: array literal.  See [Primitive Types (Arrays)].
-* `[expr; len]`: array literal containing `len` copies of `expr`.  See [Primitive Types (Arrays)].
-* `[type; len]`: array type containing `len` instances of `type`.  See [Primitive Types (Arrays)].
-* `expr[expr]`: collection indexing.  Overloadable (`Index`, `IndexMut`).
-* `expr[..]`, `expr[a..]`, `expr[..b]`, `expr[a..b]`: collection indexing pretending to be collection slicing, using `Range`, `RangeFrom`, `RangeTo`, `RangeFull` as the "index".
-
-[`const` and `static` (`static`)]: const-and-static.html#static
-[`const` and `static`]: const-and-static.html
-[`if let`]: if-let.html
-[`if`]: if.html
-[`type` Aliases]: type-aliases.html
-[Associated Types]: associated-types.html
-[Attributes]: attributes.html
-[Casting Between Types (`as`)]: casting-between-types.html#as
-[Closures (`move` closures)]: closures.html#move-closures
-[Closures]: closures.html
-[Comments]: comments.html
-[Crates and Modules (Defining Modules)]: crates-and-modules.html#defining-modules
-[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#exporting-a-public-interface
-[Crates and Modules (Importing External Crates)]: crates-and-modules.html#importing-external-crates
-[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#importing-modules-with-use
-[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#re-exporting-with-pub-use
-[Diverging Functions]: functions.html#diverging-functions
-[Enums]: enums.html
-[Foreign Function Interface]: ffi.html
-[Functions (Early Returns)]: functions.html#early-returns
-[Functions]: functions.html
-[Generics]: generics.html
-[Iterators]: iterators.html
-[`try!` macro]: error-handling.html#the-try-macro
-[Lifetimes]: lifetimes.html
-[Loops (`for`)]: loops.html#for
-[Loops (`loop`)]: loops.html#loop
-[Loops (`while`)]: loops.html#while
-[Loops (Ending Iteration Early)]: loops.html#ending-iteration-early
-[Loops (Loops Labels)]: loops.html#loop-labels
-[Macros]: macros.html
-[Match]: match.html
-[Method Syntax (Method Calls)]: method-syntax.html#method-calls
-[Method Syntax]: method-syntax.html
-[Mutability]: mutability.html
-[Operators and Overloading]: operators-and-overloading.html
-[Patterns (`ref` and `ref mut`)]: patterns.html#ref-and-ref-mut
-[Patterns (Bindings)]: patterns.html#bindings
-[Patterns (Ignoring bindings)]: patterns.html#ignoring-bindings
-[Patterns (Multiple patterns)]: patterns.html#multiple-patterns
-[Patterns (Ranges)]: patterns.html#ranges
-[Primitive Types (`char`)]: primitive-types.html#char
-[Primitive Types (Arrays)]: primitive-types.html#arrays
-[Primitive Types (Booleans)]: primitive-types.html#booleans
-[Primitive Types (Tuple Indexing)]: primitive-types.html#tuple-indexing
-[Primitive Types (Tuples)]: primitive-types.html#tuples
-[Raw Pointers]: raw-pointers.html
-[Reference (Byte String Literals)]: ../reference/tokens.html/#byte-string-literals
-[Reference (Integer literals)]: ../reference/tokens.html#integer-literals
-[Reference (Raw Byte String Literals)]: ../reference/tokens.html#raw-byte-string-literals
-[Reference (Raw String Literals)]: ../reference/tokens.html#raw-string-literals
-[References and Borrowing]: references-and-borrowing.html
-[Strings]: strings.html
-[Structs (Update syntax)]: structs.html#update-syntax
-[Structs]: structs.html
-[Traits (`where` clause)]: traits.html#where-clause
-[Traits (Multiple Trait Bounds)]: traits.html#multiple-trait-bounds
-[Traits]: traits.html
-[Universal Function Call Syntax]: ufcs.html
-[Universal Function Call Syntax (Angle-bracket Form)]: ufcs.html#angle-bracket-form
-[Unsafe]: unsafe.html
-[Unsized Types (`?Sized`)]: unsized-types.html#sized
-[Variable Bindings]: variable-bindings.html
diff --git a/src/doc/book/src/testing.md b/src/doc/book/src/testing.md
deleted file mode 100644 (file)
index b4f580f..0000000
+++ /dev/null
@@ -1,633 +0,0 @@
-# Testing
-
-> Program testing can be a very effective way to show the presence of bugs, but
-> it is hopelessly inadequate for showing their absence.
->
-> Edsger W. Dijkstra, "The Humble Programmer" (1972)
-
-Let's talk about how to test Rust code. What we will not be talking about is
-the right way to test Rust code. There are many schools of thought regarding
-the right and wrong way to write tests. All of these approaches use the same
-basic tools, and so we'll show you the syntax for using them.
-
-# The `test` attribute
-
-At its simplest, a test in Rust is a function that's annotated with the `test`
-attribute. Let's make a new project with Cargo called `adder`:
-
-```bash
-$ cargo new adder
-$ cd adder
-```
-
-Cargo will automatically generate a simple test when you make a new project.
-Here's the contents of `src/lib.rs`:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn it_works() {
-    }
-}
-```
-
-For now, let's remove the `mod` bit, and focus on just the function:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-#[test]
-fn it_works() {
-}
-```
-
-Note the `#[test]`. This attribute indicates that this is a test function. It
-currently has no body. That's good enough to pass! We can run the tests with
-`cargo test`:
-
-```bash
-$ cargo test
-   Compiling adder v0.1.0 (file:///home/you/projects/adder)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.15 secs
-     Running target/debug/deps/adder-941f01916ca4a642
-
-running 1 test
-test it_works ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-
-   Doc-tests adder
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-```
-
-Cargo compiled and ran our tests. There are two sets of output here: one
-for the test we wrote, and another for documentation tests. We'll talk about
-those later. For now, see this line:
-
-```text
-test it_works ... ok
-```
-
-Note the `it_works`. This comes from the name of our function:
-
-```rust
-# fn main() {
-fn it_works() {
-}
-# }
-```
-
-We also get a summary line:
-
-```text
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-```
-
-So why does our do-nothing test pass? Any test which doesn't `panic!` passes,
-and any test that does `panic!` fails. Let's make our test fail:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-#[test]
-fn it_works() {
-    assert!(false);
-}
-```
-
-`assert!` is a macro provided by Rust which takes one argument: if the argument
-is `true`, nothing happens. If the argument is `false`, it will `panic!`. Let's
-run our tests again:
-
-```bash
-$ cargo test
-   Compiling adder v0.1.0 (file:///home/you/projects/adder)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.17 secs
-     Running target/debug/deps/adder-941f01916ca4a642
-
-running 1 test
-test it_works ... FAILED
-
-failures:
-
----- it_works stdout ----
-        thread 'it_works' panicked at 'assertion failed: false', src/lib.rs:5
-note: Run with `RUST_BACKTRACE=1` for a backtrace.
-
-
-failures:
-    it_works
-
-test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
-
-error: test failed
-```
-
-Rust indicates that our test failed:
-
-```text
-test it_works ... FAILED
-```
-
-And that's reflected in the summary line:
-
-```text
-test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
-```
-
-We also get a non-zero status code. We can use `$?` on macOS and Linux:
-
-```bash
-$ echo $?
-101
-```
-
-On Windows, if you’re using `cmd`:
-
-```bash
-> echo %ERRORLEVEL%
-```
-
-And if you’re using PowerShell:
-
-```bash
-> echo $LASTEXITCODE # the code itself
-> echo $? # a boolean, fail or succeed
-```
-
-This is useful if you want to integrate `cargo test` into other tooling.
-
-We can invert our test's failure with another attribute: `should_panic`:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-#[test]
-#[should_panic]
-fn it_works() {
-    assert!(false);
-}
-```
-
-This test will now succeed if we `panic!` and fail if we complete. Let's try it:
-
-```bash
-$ cargo test
-   Compiling adder v0.1.0 (file:///home/you/projects/adder)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.17 secs
-     Running target/debug/deps/adder-941f01916ca4a642
-
-running 1 test
-test it_works ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-
-   Doc-tests adder
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-```
-
-Rust provides another macro, `assert_eq!`, that compares two arguments for
-equality:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-#[test]
-#[should_panic]
-fn it_works() {
-    assert_eq!("Hello", "world");
-}
-```
-
-Does this test pass or fail? Because of the `should_panic` attribute, it
-passes:
-
-```bash
-$ cargo test
-   Compiling adder v0.1.0 (file:///home/you/projects/adder)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.21 secs
-     Running target/debug/deps/adder-941f01916ca4a642
-
-running 1 test
-test it_works ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-
-   Doc-tests adder
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-```
-
-`should_panic` tests can be fragile, as it's hard to guarantee that the test
-didn't fail for an unexpected reason. To help with this, an optional `expected`
-parameter can be added to the `should_panic` attribute. The test harness will
-make sure that the failure message contains the provided text. A safer version
-of the example above would be:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-#[test]
-#[should_panic(expected = "assertion failed")]
-fn it_works() {
-    assert_eq!("Hello", "world");
-}
-```
-
-That's all there is to the basics! Let's write one 'real' test:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-pub fn add_two(a: i32) -> i32 {
-    a + 2
-}
-
-#[test]
-fn it_works() {
-    assert_eq!(4, add_two(2));
-}
-```
-
-This is a very common use of `assert_eq!`: call some function with
-some known arguments and compare it to the expected output.
-
-# The `ignore` attribute
-
-Sometimes a few specific tests can be very time-consuming to execute. These
-can be disabled by default by using the `ignore` attribute:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-pub fn add_two(a: i32) -> i32 {
-    a + 2
-}
-
-#[test]
-fn it_works() {
-    assert_eq!(4, add_two(2));
-}
-
-#[test]
-#[ignore]
-fn expensive_test() {
-    // Code that takes an hour to run...
-}
-```
-
-Now we run our tests and see that `it_works` is run, but `expensive_test` is
-not:
-
-```bash
-$ cargo test
-   Compiling adder v0.1.0 (file:///home/you/projects/adder)
-    Finished debug [unoptimized + debuginfo] target(s) in 0.20 secs
-     Running target/debug/deps/adder-941f01916ca4a642
-
-running 2 tests
-test expensive_test ... ignored
-test it_works ... ok
-
-test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured
-
-   Doc-tests adder
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-```
-
-The expensive tests can be run explicitly using `cargo test -- --ignored`:
-
-```bash
-$ cargo test -- --ignored
-    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
-     Running target/debug/deps/adder-941f01916ca4a642
-
-running 1 test
-test expensive_test ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-
-   Doc-tests adder
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-```
-
-The `--ignored` argument is an argument to the test binary, and not to Cargo,
-which is why the command is `cargo test -- --ignored`.
-
-# The `tests` module
-
-There is one way in which our existing example is not idiomatic: it's
-missing the `tests` module. You might have noticed this test module was
-present in the code that was initially generated with `cargo new` but
-was missing from our last example. Let's explain what this does.
-
-The idiomatic way of writing our example looks like this:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-pub fn add_two(a: i32) -> i32 {
-    a + 2
-}
-
-#[cfg(test)]
-mod tests {
-    use super::add_two;
-
-    #[test]
-    fn it_works() {
-        assert_eq!(4, add_two(2));
-    }
-}
-```
-
-There's a few changes here. The first is the introduction of a `mod tests` with
-a `cfg` attribute. The module allows us to group all of our tests together, and
-to also define helper functions if needed, that don't become a part of the rest
-of our crate. The `cfg` attribute only compiles our test code if we're
-currently trying to run the tests. This can save compile time, and also ensures
-that our tests are entirely left out of a normal build.
-
-The second change is the `use` declaration. Because we're in an inner module,
-we need to bring the tested function into scope. This can be annoying if you have
-a large module, and so this is a common use of globs. Let's change our
-`src/lib.rs` to make use of it:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-pub fn add_two(a: i32) -> i32 {
-    a + 2
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn it_works() {
-        assert_eq!(4, add_two(2));
-    }
-}
-```
-
-Note the different `use` line. Now we run our tests:
-
-```bash
-$ cargo test
-    Updating registry `https://github.com/rust-lang/crates.io-index`
-   Compiling adder v0.1.0 (file:///home/you/projects/adder)
-     Running target/debug/deps/adder-91b3e234d4ed382a
-
-running 1 test
-test tests::it_works ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-
-   Doc-tests adder
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-```
-
-It works!
-
-The current convention is to use the `tests` module to hold your "unit-style"
-tests. Anything that tests one small bit of functionality makes sense to
-go here. But what about "integration-style" tests instead? For that, we have
-the `tests` directory.
-
-# The `tests` directory
-
-Each file in `tests/*.rs` directory is treated as an individual crate.
-To write an integration test, let's make a `tests` directory and
-put a `tests/integration_test.rs` file inside with this as its contents:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-# // Sadly, this code will not work in play.rust-lang.org, because we have no
-# // crate adder to import. You'll need to try this part on your own machine.
-extern crate adder;
-
-#[test]
-fn it_works() {
-    assert_eq!(4, adder::add_two(2));
-}
-```
-
-This looks similar to our previous tests, but slightly different. We now have
-an `extern crate adder` at the top. This is because each test in the `tests`
-directory is an entirely separate crate, and so we need to import our library.
-This is also why `tests` is a suitable place to write integration-style tests:
-they use the library like any other consumer of it would.
-
-Let's run them:
-
-```bash
-$ cargo test
-   Compiling adder v0.1.0 (file:///home/you/projects/adder)
-     Running target/debug/deps/adder-91b3e234d4ed382a
-
-running 1 test
-test tests::it_works ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-
-     Running target/debug/integration_test-68064b69521c828a
-
-running 1 test
-test it_works ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-
-   Doc-tests adder
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-```
-
-Now we have three sections: our previous test is also run, as well as our new
-one.
-
-Cargo will ignore files in subdirectories of the `tests/` directory.
-Therefore shared modules in integrations tests are possible.
-For example `tests/common/mod.rs` is not separately compiled by cargo but can
-be imported in every test with `mod common;`
-
-That's all there is to the `tests` directory. The `tests` module isn't needed
-here, since the whole thing is focused on tests.
-
-Note, when building integration tests, cargo will not pass the `test` attribute
-to the compiler. It means that all parts in `cfg(test)` won't be included in
-the build used in your integration tests.
-
-Let's finally check out that third section: documentation tests.
-
-# Documentation tests
-
-Nothing is better than documentation with examples. Nothing is worse than
-examples that don't actually work, because the code has changed since the
-documentation has been written. To this end, Rust supports automatically
-running examples in your documentation (**note:** this only works in library
-crates, not binary crates). Here's a fleshed-out `src/lib.rs` with examples:
-
-```rust,ignore
-# // The next line exists to trick play.rust-lang.org into running our code as a
-# // test:
-# // fn main
-#
-//! The `adder` crate provides functions that add numbers to other numbers.
-//!
-//! # Examples
-//!
-//! ```
-//! assert_eq!(4, adder::add_two(2));
-//! ```
-
-/// This function adds two to its argument.
-///
-/// # Examples
-///
-/// ```
-/// use adder::add_two;
-///
-/// assert_eq!(4, add_two(2));
-/// ```
-pub fn add_two(a: i32) -> i32 {
-    a + 2
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn it_works() {
-        assert_eq!(4, add_two(2));
-    }
-}
-```
-
-Note the module-level documentation with `//!` and the function-level
-documentation with `///`. Rust's documentation supports Markdown in comments,
-and so triple graves mark code blocks. It is conventional to include the
-`# Examples` section, exactly like that, with examples following.
-
-Let's run the tests again:
-
-```bash
-$ cargo test
-   Compiling adder v0.1.0. (file:///home/you/projects/adder)
-     Running target/debug/deps/adder-91b3e234d4ed382a
-
-running 1 test
-test tests::it_works ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-
-     Running target/debug/integration_test-68064b69521c828a
-
-running 1 test
-test it_works ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-
-   Doc-tests adder
-
-running 2 tests
-test add_two_0 ... ok
-test _0 ... ok
-
-test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
-```
-
-Now we have all three kinds of tests running! Note the names of the
-documentation tests: the `_0` is generated for the module test, and `add_two_0`
-for the function test. These will auto increment with names like `add_two_1` as
-you add more examples.
-
-We haven’t covered all of the details with writing documentation tests. For more,
-please see the [Documentation chapter](documentation.html).
-
-# Testing and concurrency
-
-It is important to note that tests are run concurrently using threads. For this
-reason, care should be taken to ensure your tests do not depend on each-other,
-or on any shared state. "Shared state" can also include the environment, such
-as the current working directory, or environment variables.
-
-If this is an issue it is possible to control this concurrency, either by
-setting the environment variable `RUST_TEST_THREADS`, or by passing the argument
-`--test-threads` to the tests:
-
-```bash
-$ RUST_TEST_THREADS=1 cargo test   # Run tests with no concurrency
-...
-$ cargo test -- --test-threads=1   # Same as above
-...
-```
-
-# Test output
-
-By default Rust's test library captures and discards output to standard
-out/error, e.g. output from `println!()`. This too can be controlled using the
-environment or a switch:
-
-
-```bash
-$ RUST_TEST_NOCAPTURE=1 cargo test   # Preserve stdout/stderr
-...
-$ cargo test -- --nocapture          # Same as above
-...
-```
-
-However a better method avoiding capture is to use logging rather than raw
-output. Rust has a [standard logging API][log], which provides a frontend to
-multiple logging implementations. This can be used in conjunction with the
-default [env_logger] to output any debugging information in a manner that can be
-controlled at runtime.
-
-[log]: https://crates.io/crates/log
-[env_logger]: https://crates.io/crates/env_logger
diff --git a/src/doc/book/src/the-stack-and-the-heap.md b/src/doc/book/src/the-stack-and-the-heap.md
deleted file mode 100644 (file)
index 6866505..0000000
+++ /dev/null
@@ -1,583 +0,0 @@
-# The Stack and the Heap
-
-As a systems language, Rust operates at a low level. If you’re coming from a
-high-level language, there are some aspects of systems programming that you may
-not be familiar with. The most important one is how memory works, with a stack
-and a heap. If you’re familiar with how C-like languages use stack allocation,
-this chapter will be a refresher. If you’re not, you’ll learn about this more
-general concept, but with a Rust-y focus.
-
-As with most things, when learning about them, we’ll use a simplified model to
-start. This lets you get a handle on the basics, without getting bogged down
-with details which are, for now, irrelevant. The examples we’ll use aren’t 100%
-accurate, but are representative for the level we’re trying to learn at right
-now. Once you have the basics down, learning more about how allocators are
-implemented, virtual memory, and other advanced topics will reveal the leaks in
-this particular abstraction.
-
-# Memory management
-
-These two terms are about memory management. The stack and the heap are
-abstractions that help you determine when to allocate and deallocate memory.
-
-Here’s a high-level comparison:
-
-The stack is very fast, and is where memory is allocated in Rust by default.
-But the allocation is local to a function call, and is limited in size. The
-heap, on the other hand, is slower, and is explicitly allocated by your
-program. But it’s effectively unlimited in size, and is globally accessible.
-Note this meaning of heap, which allocates arbitrary-sized blocks of memory in arbitrary
-order, is quite different from the heap data structure.  
-
-# The Stack
-
-Let’s talk about this Rust program:
-
-```rust
-fn main() {
-    let x = 42;
-}
-```
-
-This program has one variable binding, `x`. This memory needs to be allocated
-from somewhere. Rust ‘stack allocates’ by default, which means that basic
-values ‘go on the stack’. What does that mean?
-
-Well, when a function gets called, some memory gets allocated for all of its
-local variables and some other information. This is called a ‘stack frame’, and
-for the purpose of this tutorial, we’re going to ignore the extra information
-and only consider the local variables we’re allocating. So in this case, when
-`main()` is run, we’ll allocate a single 32-bit integer for our stack frame.
-This is automatically handled for you, as you can see; we didn’t have to write
-any special Rust code or anything.
-
-When the function exits, its stack frame gets deallocated. This happens
-automatically as well.
-
-That’s all there is for this simple program. The key thing to understand here
-is that stack allocation is very, very fast. Since we know all the local
-variables we have ahead of time, we can grab the memory all at once. And since
-we’ll throw them all away at the same time as well, we can get rid of it very
-fast too.
-
-The downside is that we can’t keep values around if we need them for longer
-than a single function. We also haven’t talked about what the word, ‘stack’,
-means. To do that, we need a slightly more complicated example:
-
-```rust
-fn foo() {
-    let y = 5;
-    let z = 100;
-}
-
-fn main() {
-    let x = 42;
-
-    foo();
-}
-```
-
-This program has three variables total: two in `foo()`, one in `main()`. Just
-as before, when `main()` is called, a single integer is allocated for its stack
-frame. But before we can show what happens when `foo()` is called, we need to
-visualize what’s going on with memory. Your operating system presents a view of
-memory to your program that’s pretty simple: a huge list of addresses, from 0
-to a large number, representing how much RAM your computer has. For example, if
-you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,823`. That
-number comes from 2<sup>30</sup>, the number of bytes in a gigabyte. [^gigabyte]
-
-[^gigabyte]: ‘Gigabyte’ can mean two things: 10<sup>9</sup>, or 2<sup>30</sup>. The IEC standard resolved this by stating that ‘gigabyte’ is 10<sup>9</sup>, and ‘gibibyte’ is 2<sup>30</sup>. However, very few people use this terminology, and rely on context to differentiate. We follow in that tradition here.
-
-This memory is kind of like a giant array: addresses start at zero and go
-up to the final number. So here’s a diagram of our first stack frame:
-
-| Address | Name | Value |
-|---------|------|-------|
-| 0       | x    | 42    |
-
-We’ve got `x` located at address `0`, with the value `42`.
-
-When `foo()` is called, a new stack frame is allocated:
-
-| Address | Name | Value |
-|---------|------|-------|
-| 2       | z    | 100   |
-| 1       | y    | 5     |
-| 0       | x    | 42    |
-
-Because `0` was taken by the first frame, `1` and `2` are used for `foo()`’s
-stack frame. It grows upward, the more functions we call.
-
-
-There are some important things we have to take note of here. The numbers 0, 1,
-and 2 are all solely for illustrative purposes, and bear no relationship to the
-address values the computer will use in reality. In particular, the series of
-addresses are in reality going to be separated by some number of bytes that
-separate each address, and that separation may even exceed the size of the
-value being stored.
-
-After `foo()` is over, its frame is deallocated:
-
-| Address | Name | Value |
-|---------|------|-------|
-| 0       | x    | 42    |
-
-And then, after `main()`, even this last value goes away. Easy!
-
-It’s called a ‘stack’ because it works like a stack of dinner plates: the first
-plate you put down is the last plate to pick back up. Stacks are sometimes
-called ‘last in, first out queues’ for this reason, as the last value you put
-on the stack is the first one you retrieve from it.
-
-Let’s try a three-deep example:
-
-```rust
-fn italic() {
-    let i = 6;
-}
-
-fn bold() {
-    let a = 5;
-    let b = 100;
-    let c = 1;
-
-    italic();
-}
-
-fn main() {
-    let x = 42;
-
-    bold();
-}
-```
-
-We have some kooky function names to make the diagrams clearer.
-
-Okay, first, we call `main()`:
-
-| Address | Name | Value |
-|---------|------|-------|
-| 0       | x    | 42    |
-
-Next up, `main()` calls `bold()`:
-
-| Address | Name | Value |
-|---------|------|-------|
-| **3**   | **c**|**1**  |
-| **2**   | **b**|**100**|
-| **1**   | **a**| **5** |
-| 0       | x    | 42    |
-
-And then `bold()` calls `italic()`:
-
-| Address | Name | Value |
-|---------|------|-------|
-| *4*     | *i*  | *6*   |
-| **3**   | **c**|**1**  |
-| **2**   | **b**|**100**|
-| **1**   | **a**| **5** |
-| 0       | x    | 42    |
-
-Whew! Our stack is growing tall.
-
-After `italic()` is over, its frame is deallocated, leaving only `bold()` and
-`main()`:
-
-| Address | Name | Value |
-|---------|------|-------|
-| **3**   | **c**|**1**  |
-| **2**   | **b**|**100**|
-| **1**   | **a**| **5** |
-| 0       | x    | 42    |
-
-And then `bold()` ends, leaving only `main()`:
-
-| Address | Name | Value |
-|---------|------|-------|
-| 0       | x    | 42    |
-
-And then we’re done. Getting the hang of it? It’s like piling up dishes: you
-add to the top, you take away from the top.
-
-# The Heap
-
-Now, this works pretty well, but not everything can work like this. Sometimes,
-you need to pass some memory between different functions, or keep it alive for
-longer than a single function’s execution. For this, we can use the heap.
-
-In Rust, you can allocate memory on the heap with the [`Box<T>` type][box].
-Here’s an example:
-
-```rust
-fn main() {
-    let x = Box::new(5);
-    let y = 42;
-}
-```
-
-[box]: ../std/boxed/index.html
-
-Here’s what happens in memory when `main()` is called:
-
-| Address | Name | Value  |
-|---------|------|--------|
-| 1       | y    | 42     |
-| 0       | x    | ?????? |
-
-We allocate space for two variables on the stack. `y` is `42`, as it always has
-been, but what about `x`? Well, `x` is a `Box<i32>`, and boxes allocate memory
-on the heap. The actual value of the box is a structure which has a pointer to
-‘the heap’. When we start executing the function, and `Box::new()` is called,
-it allocates some memory for the heap, and puts `5` there. The memory now looks
-like this:
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 5                      |
-| ...                  | ...  | ...                    |
-| 1                    | y    | 42                     |
-| 0                    | x    | → (2<sup>30</sup>) - 1 |
-
-We have (2<sup>30</sup>) - 1 addresses in our hypothetical computer with 1GB of RAM. And since
-our stack grows from zero, the easiest place to allocate memory is from the
-other end. So our first value is at the highest place in memory. And the value
-of the struct at `x` has a [raw pointer][rawpointer] to the place we’ve
-allocated on the heap, so the value of `x` is (2<sup>30</sup>) - 1, the memory
-location we’ve asked for.
-
-[rawpointer]: raw-pointers.html
-
-We haven’t really talked too much about what it actually means to allocate and
-deallocate memory in these contexts. Getting into very deep detail is out of
-the scope of this tutorial, but what’s important to point out here is that
-the heap isn’t a stack that grows from the opposite end. We’ll have an
-example of this later in the book, but because the heap can be allocated and
-freed in any order, it can end up with ‘holes’. Here’s a diagram of the memory
-layout of a program which has been running for a while now:
-
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 5                      |
-| (2<sup>30</sup>) - 2 |      |                        |
-| (2<sup>30</sup>) - 3 |      |                        |
-| (2<sup>30</sup>) - 4 |      | 42                     |
-| ...                  | ...  | ...                    |
-| 2                    | z    | → (2<sup>30</sup>) - 4 |
-| 1                    | y    | 42                     |
-| 0                    | x    | → (2<sup>30</sup>) - 1 |
-
-In this case, we’ve allocated four things on the heap, but deallocated two of
-them. There’s a gap between (2<sup>30</sup>) - 1 and (2<sup>30</sup>) - 4 which isn’t
-currently being used. The specific details of how and why this happens depends
-on what kind of strategy you use to manage the heap. Different programs can use
-different ‘memory allocators’, which are libraries that manage this for you.
-Rust programs use [jemalloc][jemalloc] for this purpose.
-
-[jemalloc]: http://www.canonware.com/jemalloc/
-
-Anyway, back to our example. Since this memory is on the heap, it can stay
-alive longer than the function which allocates the box. In this case, however,
-it doesn’t.[^moving] When the function is over, we need to free the stack frame
-for `main()`. `Box<T>`, though, has a trick up its sleeve: [Drop][drop]. The
-implementation of `Drop` for `Box` deallocates the memory that was allocated
-when it was created. Great! So when `x` goes away, it first frees the memory
-allocated on the heap:
-
-| Address | Name | Value  |
-|---------|------|--------|
-| 1       | y    | 42     |
-| 0       | x    | ?????? |
-
-[drop]: drop.html
-[^moving]: We can make the memory live longer by transferring ownership,
-           sometimes called ‘moving out of the box’. More complex examples will
-           be covered later.
-
-
-And then the stack frame goes away, freeing all of our memory.
-
-# Arguments and borrowing
-
-We’ve got some basic examples with the stack and the heap going, but what about
-function arguments and borrowing? Here’s a small Rust program:
-
-```rust
-fn foo(i: &i32) {
-    let z = 42;
-}
-
-fn main() {
-    let x = 5;
-    let y = &x;
-
-    foo(y);
-}
-```
-
-When we enter `main()`, memory looks like this:
-
-| Address | Name | Value  |
-|---------|------|--------|
-| 1       | y    | → 0    |
-| 0       | x    | 5      |
-
-`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the
-memory location that `x` lives at, which in this case is `0`.
-
-What about when we call `foo()`, passing `y` as an argument?
-
-| Address | Name | Value  |
-|---------|------|--------|
-| 3       | z    | 42     |
-| 2       | i    | → 0    |
-| 1       | y    | → 0    |
-| 0       | x    | 5      |
-
-Stack frames aren’t only for local bindings, they’re for arguments too. So in
-this case, we need to have both `i`, our argument, and `z`, our local variable
-binding. `i` is a copy of the argument, `y`. Since `y`’s value is `0`, so is
-`i`’s.
-
-This is one reason why borrowing a variable doesn’t deallocate any memory: the
-value of a reference is a pointer to a memory location. If we got rid of
-the underlying memory, things wouldn’t work very well.
-
-# A complex example
-
-Okay, let’s go through this complex program step-by-step:
-
-```rust
-fn foo(x: &i32) {
-    let y = 10;
-    let z = &y;
-
-    baz(z);
-    bar(x, z);
-}
-
-fn bar(a: &i32, b: &i32) {
-    let c = 5;
-    let d = Box::new(5);
-    let e = &d;
-
-    baz(e);
-}
-
-fn baz(f: &i32) {
-    let g = 100;
-}
-
-fn main() {
-    let h = 3;
-    let i = Box::new(20);
-    let j = &h;
-
-    foo(j);
-}
-```
-
-First, we call `main()`:
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 20                     |
-| ...                  | ...  | ...                    |
-| 2                    | j    | → 0                    |
-| 1                    | i    | → (2<sup>30</sup>) - 1 |
-| 0                    | h    | 3                      |
-
-We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
-value pointing there.
-
-Next, at the end of `main()`, `foo()` gets called:
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 20                     |
-| ...                  | ...  | ...                    |
-| 5                    | z    | → 4                    |
-| 4                    | y    | 10                     |
-| 3                    | x    | → 0                    |
-| 2                    | j    | → 0                    |
-| 1                    | i    | → (2<sup>30</sup>) - 1 |
-| 0                    | h    | 3                      |
-
-Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
-as `j`, since that’s what we passed it in. It’s a pointer to the `0` address,
-since `j` points at `h`.
-
-Next, `foo()` calls `baz()`, passing `z`:
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 20                     |
-| ...                  | ...  | ...                    |
-| 7                    | g    | 100                    |
-| 6                    | f    | → 4                    |
-| 5                    | z    | → 4                    |
-| 4                    | y    | 10                     |
-| 3                    | x    | → 0                    |
-| 2                    | j    | → 0                    |
-| 1                    | i    | → (2<sup>30</sup>) - 1 |
-| 0                    | h    | 3                      |
-
-We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s
-over, we get rid of its stack frame:
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 20                     |
-| ...                  | ...  | ...                    |
-| 5                    | z    | → 4                    |
-| 4                    | y    | 10                     |
-| 3                    | x    | → 0                    |
-| 2                    | j    | → 0                    |
-| 1                    | i    | → (2<sup>30</sup>) - 1 |
-| 0                    | h    | 3                      |
-
-Next, `foo()` calls `bar()` with `x` and `z`:
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 20                     |
-| (2<sup>30</sup>) - 2 |      | 5                      |
-| ...                  | ...  | ...                    |
-| 10                   | e    | → 9                    |
-| 9                    | d    | → (2<sup>30</sup>) - 2 |
-| 8                    | c    | 5                      |
-| 7                    | b    | → 4                    |
-| 6                    | a    | → 0                    |
-| 5                    | z    | → 4                    |
-| 4                    | y    | 10                     |
-| 3                    | x    | → 0                    |
-| 2                    | j    | → 0                    |
-| 1                    | i    | → (2<sup>30</sup>) - 1 |
-| 0                    | h    | 3                      |
-
-We end up allocating another value on the heap, and so we have to subtract one
-from (2<sup>30</sup>) - 1. It’s easier to write that than `1,073,741,822`. In any
-case, we set up the variables as usual.
-
-At the end of `bar()`, it calls `baz()`:
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 20                     |
-| (2<sup>30</sup>) - 2 |      | 5                      |
-| ...                  | ...  | ...                    |
-| 12                   | g    | 100                    |
-| 11                   | f    | → (2<sup>30</sup>) - 2 |
-| 10                   | e    | → 9                    |
-| 9                    | d    | → (2<sup>30</sup>) - 2 |
-| 8                    | c    | 5                      |
-| 7                    | b    | → 4                    |
-| 6                    | a    | → 0                    |
-| 5                    | z    | → 4                    |
-| 4                    | y    | 10                     |
-| 3                    | x    | → 0                    |
-| 2                    | j    | → 0                    |
-| 1                    | i    | → (2<sup>30</sup>) - 1 |
-| 0                    | h    | 3                      |
-
-With this, we’re at our deepest point! Whew! Congrats for following along this
-far.
-
-After `baz()` is over, we get rid of `f` and `g`:
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 20                     |
-| (2<sup>30</sup>) - 2 |      | 5                      |
-| ...                  | ...  | ...                    |
-| 10                   | e    | → 9                    |
-| 9                    | d    | → (2<sup>30</sup>) - 2 |
-| 8                    | c    | 5                      |
-| 7                    | b    | → 4                    |
-| 6                    | a    | → 0                    |
-| 5                    | z    | → 4                    |
-| 4                    | y    | 10                     |
-| 3                    | x    | → 0                    |
-| 2                    | j    | → 0                    |
-| 1                    | i    | → (2<sup>30</sup>) - 1 |
-| 0                    | h    | 3                      |
-
-Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
-what it points to: (2<sup>30</sup>) - 2.
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 20                     |
-| ...                  | ...  | ...                    |
-| 5                    | z    | → 4                    |
-| 4                    | y    | 10                     |
-| 3                    | x    | → 0                    |
-| 2                    | j    | → 0                    |
-| 1                    | i    | → (2<sup>30</sup>) - 1 |
-| 0                    | h    | 3                      |
-
-And after that, `foo()` returns:
-
-| Address              | Name | Value                  |
-|----------------------|------|------------------------|
-| (2<sup>30</sup>) - 1 |      | 20                     |
-| ...                  | ...  | ...                    |
-| 2                    | j    | → 0                    |
-| 1                    | i    | → (2<sup>30</sup>) - 1 |
-| 0                    | h    | 3                      |
-
-And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
-it will clean up the last of the heap too.
-
-# What do other languages do?
-
-Most languages with a garbage collector heap-allocate by default. This means
-that every value is boxed. There are a number of reasons why this is done, but
-they’re out of scope for this tutorial. There are some possible optimizations
-that don’t make it true 100% of the time, too. Rather than relying on the stack
-and `Drop` to clean up memory, the garbage collector deals with the heap
-instead.
-
-# Which to use?
-
-So if the stack is faster and easier to manage, why do we need the heap? A big
-reason is that Stack-allocation alone means you only have 'Last In First Out (LIFO)' semantics for
-reclaiming storage. Heap-allocation is strictly more general, allowing storage
-to be taken from and returned to the pool in arbitrary order, but at a
-complexity cost.
-
-Generally, you should prefer stack allocation, and so, Rust stack-allocates by
-default. The LIFO model of the stack is simpler, at a fundamental level. This
-has two big impacts: runtime efficiency and semantic impact.
-
-## Runtime Efficiency
-
-Managing the memory for the stack is trivial: The machine
-increments or decrements a single value, the so-called “stack pointer”.
-Managing memory for the heap is non-trivial: heap-allocated memory is freed at
-arbitrary points, and each block of heap-allocated memory can be of arbitrary
-size, so the memory manager must generally work much harder to
-identify memory for reuse.
-
-If you’d like to dive into this topic in greater detail, [this paper][wilson]
-is a great introduction.
-
-[wilson]: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.143.4688
-
-## Semantic impact
-
-Stack-allocation impacts the Rust language itself, and thus the developer’s
-mental model. The LIFO semantics is what drives how the Rust language handles
-automatic memory management. Even the deallocation of a uniquely-owned
-heap-allocated box can be driven by the stack-based LIFO semantics, as
-discussed throughout this chapter. The flexibility (i.e. expressiveness) of non
-LIFO-semantics means that in general the compiler cannot automatically infer at
-compile-time where memory should be freed; it has to rely on dynamic protocols,
-potentially from outside the language itself, to drive deallocation (reference
-counting, as used by `Rc<T>` and `Arc<T>`, is one example of this).
-
-When taken to the extreme, the increased expressive power of heap allocation
-comes at the cost of either significant runtime support (e.g. in the form of a
-garbage collector) or significant programmer effort (in the form of explicit
-memory management calls that require verification not provided by the Rust
-compiler).
diff --git a/src/doc/book/src/trait-objects.md b/src/doc/book/src/trait-objects.md
deleted file mode 100644 (file)
index a77d5fe..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-# Trait Objects
-
-When code involves polymorphism, there needs to be a mechanism to determine
-which specific version is actually run. This is called ‘dispatch’. There are
-two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
-favors static dispatch, it also supports dynamic dispatch through a mechanism
-called ‘trait objects’.
-
-## Background
-
-For the rest of this chapter, we’ll need a trait and some implementations.
-Let’s make a simple one, `Foo`. It has one method that is expected to return a
-`String`.
-
-```rust
-trait Foo {
-    fn method(&self) -> String;
-}
-```
-
-We’ll also implement this trait for `u8` and `String`:
-
-```rust
-# trait Foo { fn method(&self) -> String; }
-impl Foo for u8 {
-    fn method(&self) -> String { format!("u8: {}", *self) }
-}
-
-impl Foo for String {
-    fn method(&self) -> String { format!("string: {}", *self) }
-}
-```
-
-
-## Static dispatch
-
-We can use this trait to perform static dispatch with trait bounds:
-
-```rust
-# trait Foo { fn method(&self) -> String; }
-# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
-# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
-fn do_something<T: Foo>(x: T) {
-    x.method();
-}
-
-fn main() {
-    let x = 5u8;
-    let y = "Hello".to_string();
-
-    do_something(x);
-    do_something(y);
-}
-```
-
-Rust uses ‘monomorphization’ to perform static dispatch here. This means that
-Rust will create a special version of `do_something()` for both `u8` and
-`String`, and then replace the call sites with calls to these specialized
-functions. In other words, Rust generates something like this:
-
-```rust
-# trait Foo { fn method(&self) -> String; }
-# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
-# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
-fn do_something_u8(x: u8) {
-    x.method();
-}
-
-fn do_something_string(x: String) {
-    x.method();
-}
-
-fn main() {
-    let x = 5u8;
-    let y = "Hello".to_string();
-
-    do_something_u8(x);
-    do_something_string(y);
-}
-```
-
-This has a great upside: static dispatch allows function calls to be
-inlined because the callee is known at compile time, and inlining is
-the key to good optimization. Static dispatch is fast, but it comes at
-a tradeoff: ‘code bloat’, due to many copies of the same function
-existing in the binary, one for each type.
-
-Furthermore, compilers aren’t perfect and may “optimize” code to become slower.
-For example, functions inlined too eagerly will bloat the instruction cache
-(cache rules everything around us). This is part of the reason that `#[inline]`
-and `#[inline(always)]` should be used carefully, and one reason why using a
-dynamic dispatch is sometimes more efficient.
-
-However, the common case is that it is more efficient to use static dispatch,
-and one can always have a thin statically-dispatched wrapper function that does
-a dynamic dispatch, but not vice versa, meaning static calls are more flexible.
-The standard library tries to be statically dispatched where possible for this
-reason.
-
-## Dynamic dispatch
-
-Rust provides dynamic dispatch through a feature called ‘trait objects’. Trait
-objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
-*any* type that implements the given trait, where the precise type can only be
-known at runtime.
-
-A trait object can be obtained from a pointer to a concrete type that
-implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it
-(e.g. using `&x` as an argument to a function that takes `&Foo`).
-
-These trait object coercions and casts also work for pointers like `&mut T` to
-`&mut Foo` and `Box<T>` to `Box<Foo>`, but that’s all at the moment. Coercions
-and casts are identical.
-
-This operation can be seen as ‘erasing’ the compiler’s knowledge about the
-specific type of the pointer, and hence trait objects are sometimes referred to
-as ‘type erasure’.
-
-Coming back to the example above, we can use the same trait to perform dynamic
-dispatch with trait objects by casting:
-
-```rust
-# trait Foo { fn method(&self) -> String; }
-# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
-# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
-fn do_something(x: &Foo) {
-    x.method();
-}
-
-fn main() {
-    let x = 5u8;
-    do_something(&x as &Foo);
-}
-```
-
-or by coercing:
-
-```rust
-# trait Foo { fn method(&self) -> String; }
-# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
-# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
-fn do_something(x: &Foo) {
-    x.method();
-}
-
-fn main() {
-    let x = "Hello".to_string();
-    do_something(&x);
-}
-```
-
-A function that takes a trait object is not specialized to each of the types
-that implements `Foo`: only one copy is generated, often (but not always)
-resulting in less code bloat. However, this comes at the cost of requiring
-slower virtual function calls, and effectively inhibiting any chance of
-inlining and related optimizations from occurring.
-
-### Why pointers?
-
-Rust does not put things behind a pointer by default, unlike many managed
-languages, so types can have different sizes. Knowing the size of the value at
-compile time is important for things like passing it as an argument to a
-function, moving it about on the stack and allocating (and deallocating) space
-on the heap to store it.
-
-For `Foo`, we would need to have a value that could be at least either a
-`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
-dependent crates may implement `Foo` (any number of bytes at all). There’s no
-way to guarantee that this last point can work if the values are stored without
-a pointer, because those other types can be arbitrarily large.
-
-Putting the value behind a pointer means the size of the value is not relevant
-when we are tossing a trait object around, only the size of the pointer itself.
-
-### Representation
-
-The methods of the trait can be called on a trait object via a special record
-of function pointers traditionally called a ‘vtable’ (created and managed by
-the compiler).
-
-Trait objects are both simple and complicated: their core representation and
-layout is quite straight-forward, but there are some curly error messages and
-surprising behaviors to discover.
-
-Let’s start simple, with the runtime representation of a trait object. The
-`std::raw` module contains structs with layouts that are the same as the
-complicated built-in types, [including trait objects][stdraw]:
-
-```rust
-# mod foo {
-pub struct TraitObject {
-    pub data: *mut (),
-    pub vtable: *mut (),
-}
-# }
-```
-
-[stdraw]: ../std/raw/struct.TraitObject.html
-
-That is, a trait object like `&Foo` consists of a ‘data’ pointer and a ‘vtable’
-pointer.
-
-The data pointer addresses the data (of some unknown type `T`) that the trait
-object is storing, and the vtable pointer points to the vtable (‘virtual method
-table’) corresponding to the implementation of `Foo` for `T`.
-
-
-A vtable is essentially a struct of function pointers, pointing to the concrete
-piece of machine code for each method in the implementation. A method call like
-`trait_object.method()` will retrieve the correct pointer out of the vtable and
-then do a dynamic call of it. For example:
-
-```rust,ignore
-struct FooVtable {
-    destructor: fn(*mut ()),
-    size: usize,
-    align: usize,
-    method: fn(*const ()) -> String,
-}
-
-// u8:
-
-fn call_method_on_u8(x: *const ()) -> String {
-    // The compiler guarantees that this function is only called
-    // with `x` pointing to a u8.
-    let byte: &u8 = unsafe { &*(x as *const u8) };
-
-    byte.method()
-}
-
-static Foo_for_u8_vtable: FooVtable = FooVtable {
-    destructor: /* compiler magic */,
-    size: 1,
-    align: 1,
-
-    // Cast to a function pointer:
-    method: call_method_on_u8 as fn(*const ()) -> String,
-};
-
-
-// String:
-
-fn call_method_on_String(x: *const ()) -> String {
-    // The compiler guarantees that this function is only called
-    // with `x` pointing to a String.
-    let string: &String = unsafe { &*(x as *const String) };
-
-    string.method()
-}
-
-static Foo_for_String_vtable: FooVtable = FooVtable {
-    destructor: /* compiler magic */,
-    // Values for a 64-bit computer, halve them for 32-bit ones.
-    size: 24,
-    align: 8,
-
-    method: call_method_on_String as fn(*const ()) -> String,
-};
-```
-
-The `destructor` field in each vtable points to a function that will clean up
-any resources of the vtable’s type: for `u8` it is trivial, but for `String` it
-will free the memory. This is necessary for owning trait objects like
-`Box<Foo>`, which need to clean-up both the `Box` allocation as well as the
-internal type when they go out of scope. The `size` and `align` fields store
-the size of the erased type, and its alignment requirements.
-
-Suppose we’ve got some values that implement `Foo`. The explicit form of
-construction and use of `Foo` trait objects might look a bit like (ignoring the
-type mismatches: they’re all pointers anyway):
-
-```rust,ignore
-let a: String = "foo".to_string();
-let x: u8 = 1;
-
-// let b: &Foo = &a;
-let b = TraitObject {
-    // Store the data:
-    data: &a,
-    // Store the methods:
-    vtable: &Foo_for_String_vtable
-};
-
-// let y: &Foo = x;
-let y = TraitObject {
-    // Store the data:
-    data: &x,
-    // Store the methods:
-    vtable: &Foo_for_u8_vtable
-};
-
-// b.method();
-(b.vtable.method)(b.data);
-
-// y.method();
-(y.vtable.method)(y.data);
-```
-
-## Object Safety
-
-Not every trait can be used to make a trait object. For example, vectors implement
-`Clone`, but if we try to make a trait object:
-
-```rust,ignore
-let v = vec![1, 2, 3];
-let o = &v as &Clone;
-```
-
-We get an error:
-
-```text
-error: cannot convert to a trait object because trait `core::clone::Clone` is not object-safe [E0038]
-let o = &v as &Clone;
-        ^~
-note: the trait cannot require that `Self : Sized`
-let o = &v as &Clone;
-        ^~
-```
-
-The error says that `Clone` is not ‘object-safe’. Only traits that are
-object-safe can be made into trait objects. A trait is object-safe if both of
-these are true:
-
-* the trait does not require that `Self: Sized`
-* all of its methods are object-safe
-
-So what makes a method object-safe? Each method must require that `Self: Sized`
-or all of the following:
-
-* must not have any type parameters
-* must not use `Self`
-
-Whew! As we can see, almost all of these rules talk about `Self`. A good intuition
-is “except in special circumstances, if your trait’s method uses `Self`, it is not
-object-safe.”
diff --git a/src/doc/book/src/traits.md b/src/doc/book/src/traits.md
deleted file mode 100644 (file)
index 19a133f..0000000
+++ /dev/null
@@ -1,551 +0,0 @@
-# Traits
-
-A trait is a language feature that tells the Rust compiler about
-functionality a type must provide.
-
-Recall the `impl` keyword, used to call a function with [method
-syntax][methodsyntax]:
-
-```rust
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-impl Circle {
-    fn area(&self) -> f64 {
-        std::f64::consts::PI * (self.radius * self.radius)
-    }
-}
-```
-
-[methodsyntax]: method-syntax.html
-
-Traits are similar, except that we first define a trait with a method
-signature, then implement the trait for a type. In this example, we implement the trait `HasArea` for `Circle`:
-
-```rust
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-trait HasArea {
-    fn area(&self) -> f64;
-}
-
-impl HasArea for Circle {
-    fn area(&self) -> f64 {
-        std::f64::consts::PI * (self.radius * self.radius)
-    }
-}
-```
-
-As you can see, the `trait` block looks very similar to the `impl` block,
-but we don’t define a body, only a type signature. When we `impl` a trait,
-we use `impl Trait for Item`, rather than only `impl Item`.
-
-`Self` may be used in a type annotation to refer to an instance of the type
-implementing this trait passed as a parameter. `Self`, `&Self` or `&mut Self`
-may be used depending on the level of ownership required.
-
-```rust
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-trait HasArea {
-    fn area(&self) -> f64;
-
-    fn is_larger(&self, &Self) -> bool;
-}
-
-impl HasArea for Circle {
-    fn area(&self) -> f64 {
-        std::f64::consts::PI * (self.radius * self.radius)
-    }
-
-    fn is_larger(&self, other: &Self) -> bool {
-        self.area() > other.area()
-    }
-}
-```
-
-## Trait bounds on generic functions
-
-Traits are useful because they allow a type to make certain promises about its
-behavior. Generic functions can exploit this to constrain, or [bound][bounds], the types they
-accept. Consider this function, which does not compile:
-
-[bounds]: glossary.html#bounds
-
-```rust,ignore
-fn print_area<T>(shape: T) {
-    println!("This shape has an area of {}", shape.area());
-}
-```
-
-Rust complains:
-
-```text
-error: no method named `area` found for type `T` in the current scope
-```
-
-Because `T` can be any type, we can’t be sure that it implements the `area`
-method. But we can add a trait bound to our generic `T`, ensuring
-that it does:
-
-```rust
-# trait HasArea {
-#     fn area(&self) -> f64;
-# }
-fn print_area<T: HasArea>(shape: T) {
-    println!("This shape has an area of {}", shape.area());
-}
-```
-
-The syntax `<T: HasArea>` means “any type that implements the `HasArea` trait.”
-Because traits define function type signatures, we can be sure that any type
-which implements `HasArea` will have an `.area()` method.
-
-Here’s an extended example of how this works:
-
-```rust
-trait HasArea {
-    fn area(&self) -> f64;
-}
-
-struct Circle {
-    x: f64,
-    y: f64,
-    radius: f64,
-}
-
-impl HasArea for Circle {
-    fn area(&self) -> f64 {
-        std::f64::consts::PI * (self.radius * self.radius)
-    }
-}
-
-struct Square {
-    x: f64,
-    y: f64,
-    side: f64,
-}
-
-impl HasArea for Square {
-    fn area(&self) -> f64 {
-        self.side * self.side
-    }
-}
-
-fn print_area<T: HasArea>(shape: T) {
-    println!("This shape has an area of {}", shape.area());
-}
-
-fn main() {
-    let c = Circle {
-        x: 0.0f64,
-        y: 0.0f64,
-        radius: 1.0f64,
-    };
-
-    let s = Square {
-        x: 0.0f64,
-        y: 0.0f64,
-        side: 1.0f64,
-    };
-
-    print_area(c);
-    print_area(s);
-}
-```
-
-This program outputs:
-
-```text
-This shape has an area of 3.141593
-This shape has an area of 1
-```
-
-As you can see, `print_area` is now generic, but also ensures that we have
-passed in the correct types. If we pass in an incorrect type:
-
-```rust,ignore
-print_area(5);
-```
-
-We get a compile-time error:
-
-```text
-error: the trait bound `_ : HasArea` is not satisfied [E0277]
-```
-
-## Trait bounds on generic structs
-
-Your generic structs can also benefit from trait bounds. All you need to
-do is append the bound when you declare type parameters. Here is a new
-type `Rectangle<T>` and its operation `is_square()`:
-
-```rust
-struct Rectangle<T> {
-    x: T,
-    y: T,
-    width: T,
-    height: T,
-}
-
-impl<T: PartialEq> Rectangle<T> {
-    fn is_square(&self) -> bool {
-        self.width == self.height
-    }
-}
-
-fn main() {
-    let mut r = Rectangle {
-        x: 0,
-        y: 0,
-        width: 47,
-        height: 47,
-    };
-
-    assert!(r.is_square());
-
-    r.height = 42;
-    assert!(!r.is_square());
-}
-```
-
-`is_square()` needs to check that the sides are equal, so the sides must be of
-a type that implements the [`core::cmp::PartialEq`][PartialEq] trait:
-
-```rust,ignore
-impl<T: PartialEq> Rectangle<T> { ... }
-```
-
-Now, a rectangle can be defined in terms of any type that can be compared for
-equality.
-
-[PartialEq]: ../core/cmp/trait.PartialEq.html
-
-Here we defined a new struct `Rectangle` that accepts numbers of any
-precision—really, objects of pretty much any type—as long as they can be
-compared for equality. Could we do the same for our `HasArea` structs, `Square`
-and `Circle`? Yes, but they need multiplication, and to work with that we need
-to know more about [operator traits][operators-and-overloading].
-
-[operators-and-overloading]: operators-and-overloading.html
-
-# Rules for implementing traits
-
-So far, we’ve only added trait implementations to structs, but you can
-implement a trait for any type such as `f32`:
-
-```rust
-trait ApproxEqual {
-    fn approx_equal(&self, other: &Self) -> bool;
-}
-impl ApproxEqual for f32 {
-    fn approx_equal(&self, other: &Self) -> bool {
-        // Appropriate for `self` and `other` being close to 1.0.
-        (self - other).abs() <= ::std::f32::EPSILON
-    }
-}
-
-println!("{}", 1.0.approx_equal(&1.00000001));
-```
-
-This may seem like the Wild West, but there are two restrictions around
-implementing traits that prevent this from getting out of hand. The first is
-that if the trait isn’t defined in your scope, it doesn’t apply. Here’s an
-example: the standard library provides a [`Write`][write] trait which adds
-extra functionality to `File`s, for doing file I/O. By default, a `File`
-won’t have its methods:
-
-[write]: ../std/io/trait.Write.html
-
-```rust,ignore
-let mut f = std::fs::File::create("foo.txt").expect("Couldn’t create foo.txt");
-let buf = b"whatever"; // buf: &[u8; 8], a byte string literal.
-let result = f.write(buf);
-# result.unwrap(); // Ignore the error.
-```
-
-Here’s the error:
-
-```text
-error: type `std::fs::File` does not implement any method in scope named `write`
-let result = f.write(buf);
-               ^~~~~~~~~~
-```
-
-We need to `use` the `Write` trait first:
-
-```rust,no_run
-use std::io::Write;
-
-let mut f = std::fs::File::create("foo.txt").expect("Couldn’t create foo.txt");
-let buf = b"whatever";
-let result = f.write(buf);
-# result.unwrap(); // Ignore the error.
-```
-
-This will compile without error.
-
-This means that even if someone does something bad like add methods to `i32`,
-it won’t affect you, unless you `use` that trait.
-
-There’s one more restriction on implementing traits: either the trait
-or the type you’re implementing it for must be defined by you. Or more
-precisely, one of them must be defined in the same crate as the `impl`
-you're writing. For more on Rust's module and package system, see the
-chapter on [crates and modules][cm].
-
-So, we could implement the `HasArea` type for `i32`, because we defined
-`HasArea` in our code. But if we tried to implement `ToString`, a trait
-provided by Rust, for `i32`, we could not, because neither the trait nor
-the type are defined in our crate.
-
-One last thing about traits: generic functions with a trait bound use
-‘monomorphization’ (mono: one, morph: form), so they are statically dispatched.
-What’s that mean? Check out the chapter on [trait objects][to] for more details.
-
-[cm]: crates-and-modules.html
-[to]: trait-objects.html
-
-# Multiple trait bounds
-
-You’ve seen that you can bound a generic type parameter with a trait:
-
-```rust
-fn foo<T: Clone>(x: T) {
-    x.clone();
-}
-```
-
-If you need more than one bound, you can use `+`:
-
-```rust
-use std::fmt::Debug;
-
-fn foo<T: Clone + Debug>(x: T) {
-    x.clone();
-    println!("{:?}", x);
-}
-```
-
-`T` now needs to be both `Clone` as well as `Debug`.
-
-# Where clause
-
-Writing functions with only a few generic types and a small number of trait
-bounds isn’t too bad, but as the number increases, the syntax gets increasingly
-awkward:
-
-```rust
-use std::fmt::Debug;
-
-fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
-    x.clone();
-    y.clone();
-    println!("{:?}", y);
-}
-```
-
-The name of the function is on the far left, and the parameter list is on the
-far right. The bounds are getting in the way.
-
-Rust has a solution, and it’s called a ‘`where` clause’:
-
-```rust
-use std::fmt::Debug;
-
-fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
-    x.clone();
-    y.clone();
-    println!("{:?}", y);
-}
-
-fn bar<T, K>(x: T, y: K) where T: Clone, K: Clone + Debug {
-    x.clone();
-    y.clone();
-    println!("{:?}", y);
-}
-
-fn main() {
-    foo("Hello", "world");
-    bar("Hello", "world");
-}
-```
-
-`foo()` uses the syntax we showed earlier, and `bar()` uses a `where` clause.
-All you need to do is leave off the bounds when defining your type parameters,
-and then add `where` after the parameter list. For longer lists, whitespace can
-be added:
-
-```rust
-use std::fmt::Debug;
-
-fn bar<T, K>(x: T, y: K)
-    where T: Clone,
-          K: Clone + Debug {
-
-    x.clone();
-    y.clone();
-    println!("{:?}", y);
-}
-```
-
-This flexibility can add clarity in complex situations.
-
-`where` is also more powerful than the simpler syntax. For example:
-
-```rust
-trait ConvertTo<Output> {
-    fn convert(&self) -> Output;
-}
-
-impl ConvertTo<i64> for i32 {
-    fn convert(&self) -> i64 { *self as i64 }
-}
-
-// Can be called with T == i32.
-fn normal<T: ConvertTo<i64>>(x: &T) -> i64 {
-    x.convert()
-}
-
-// Can be called with T == i64.
-fn inverse<T>(x: i32) -> T
-        // This is using ConvertTo as if it were "ConvertTo<i64>".
-        where i32: ConvertTo<T> {
-    x.convert()
-}
-```
-
-This shows off the additional feature of `where` clauses: they allow bounds
-on the left-hand side not only of type parameters `T`, but also of types (`i32` in this case). In this example, `i32` must implement
-`ConvertTo<T>`. Rather than defining what `i32` is (since that's obvious), the
-`where` clause here constrains `T`.
-
-# Default methods
-
-A default method can be added to a trait definition if it is already known how a typical implementor will define a method. For example, `is_invalid()` is defined as the opposite of `is_valid()`:
-
-```rust
-trait Foo {
-    fn is_valid(&self) -> bool;
-
-    fn is_invalid(&self) -> bool { !self.is_valid() }
-}
-```
-
-Implementors of the `Foo` trait need to implement `is_valid()` but not `is_invalid()` due to the added default behavior. This default behavior can still be overridden as in:
-
-```rust
-# trait Foo {
-#     fn is_valid(&self) -> bool;
-#
-#     fn is_invalid(&self) -> bool { !self.is_valid() }
-# }
-struct UseDefault;
-
-impl Foo for UseDefault {
-    fn is_valid(&self) -> bool {
-        println!("Called UseDefault.is_valid.");
-        true
-    }
-}
-
-struct OverrideDefault;
-
-impl Foo for OverrideDefault {
-    fn is_valid(&self) -> bool {
-        println!("Called OverrideDefault.is_valid.");
-        true
-    }
-
-    fn is_invalid(&self) -> bool {
-        println!("Called OverrideDefault.is_invalid!");
-        true // Overrides the expected value of `is_invalid()`.
-    }
-}
-
-let default = UseDefault;
-assert!(!default.is_invalid()); // Prints "Called UseDefault.is_valid."
-
-let over = OverrideDefault;
-assert!(over.is_invalid()); // Prints "Called OverrideDefault.is_invalid!"
-```
-
-# Inheritance
-
-Sometimes, implementing a trait requires implementing another trait:
-
-```rust
-trait Foo {
-    fn foo(&self);
-}
-
-trait FooBar : Foo {
-    fn foobar(&self);
-}
-```
-
-Implementors of `FooBar` must also implement `Foo`, like this:
-
-```rust
-# trait Foo {
-#     fn foo(&self);
-# }
-# trait FooBar : Foo {
-#     fn foobar(&self);
-# }
-struct Baz;
-
-impl Foo for Baz {
-    fn foo(&self) { println!("foo"); }
-}
-
-impl FooBar for Baz {
-    fn foobar(&self) { println!("foobar"); }
-}
-```
-
-If we forget to implement `Foo`, Rust will tell us:
-
-```text
-error: the trait bound `main::Baz : main::Foo` is not satisfied [E0277]
-```
-
-# Deriving
-
-Implementing traits like `Debug` and `Default` repeatedly can become
-quite tedious. For that reason, Rust provides an [attribute][attributes] that
-allows you to let Rust automatically implement traits for you:
-
-```rust
-#[derive(Debug)]
-struct Foo;
-
-fn main() {
-    println!("{:?}", Foo);
-}
-```
-
-[attributes]: attributes.html
-
-However, deriving is limited to a certain set of traits:
-
-- [`Clone`](../core/clone/trait.Clone.html)
-- [`Copy`](../core/marker/trait.Copy.html)
-- [`Debug`](../core/fmt/trait.Debug.html)
-- [`Default`](../core/default/trait.Default.html)
-- [`Eq`](../core/cmp/trait.Eq.html)
-- [`Hash`](../core/hash/trait.Hash.html)
-- [`Ord`](../core/cmp/trait.Ord.html)
-- [`PartialEq`](../core/cmp/trait.PartialEq.html)
-- [`PartialOrd`](../core/cmp/trait.PartialOrd.html)
diff --git a/src/doc/book/src/type-aliases.md b/src/doc/book/src/type-aliases.md
deleted file mode 100644 (file)
index 1bd0f78..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-# Type Aliases
-
-The `type` keyword lets you declare an alias of another type:
-
-```rust
-type Name = String;
-```
-
-You can then use this type as if it were a real type:
-
-```rust
-type Name = String;
-
-let x: Name = "Hello".to_string();
-```
-
-Note, however, that this is an _alias_, not a new type entirely. In other
-words, because Rust is strongly typed, you’d expect a comparison between two
-different types to fail:
-
-```rust,ignore
-let x: i32 = 5;
-let y: i64 = 5;
-
-if x == y {
-   // ...
-}
-```
-
-this gives
-
-```text
-error: mismatched types:
- expected `i32`,
-    found `i64`
-(expected i32,
-    found i64) [E0308]
-     if x == y {
-             ^
-```
-
-But, if we had an alias:
-
-```rust
-type Num = i32;
-
-let x: i32 = 5;
-let y: Num = 5;
-
-if x == y {
-   // ...
-}
-```
-
-This compiles without error. Values of a `Num` type are the same as a value of
-type `i32`, in every way. You can use [tuple struct] to really get a new type.
-
-[tuple struct]: structs.html#tuple-structs
-
-You can also use type aliases with generics:
-
-```rust
-use std::result;
-
-enum ConcreteError {
-    Foo,
-    Bar,
-}
-
-type Result<T> = result::Result<T, ConcreteError>;
-```
-
-This creates a specialized version of the `Result` type, which always has a
-`ConcreteError` for the `E` part of `Result<T, E>`. This is commonly used
-in the standard library to create custom errors for each subsection. For
-example, [io::Result][ioresult].
-
-[ioresult]: ../std/io/type.Result.html
diff --git a/src/doc/book/src/ufcs.md b/src/doc/book/src/ufcs.md
deleted file mode 100644 (file)
index 016ecc7..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-# Universal Function Call Syntax
-
-Sometimes, functions can have the same names. Consider this code:
-
-```rust
-trait Foo {
-    fn f(&self);
-}
-
-trait Bar {
-    fn f(&self);
-}
-
-struct Baz;
-
-impl Foo for Baz {
-    fn f(&self) { println!("Baz’s impl of Foo"); }
-}
-
-impl Bar for Baz {
-    fn f(&self) { println!("Baz’s impl of Bar"); }
-}
-
-let b = Baz;
-```
-
-If we were to try to call `b.f()`, we’d get an error:
-
-```text
-error: multiple applicable methods in scope [E0034]
-b.f();
-  ^~~
-note: candidate #1 is defined in an impl of the trait `main::Foo` for the type
-`main::Baz`
-    fn f(&self) { println!("Baz’s impl of Foo"); }
-    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-note: candidate #2 is defined in an impl of the trait `main::Bar` for the type
-`main::Baz`
-    fn f(&self) { println!("Baz’s impl of Bar"); }
-    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-```
-
-We need a way to disambiguate which method we need. This feature is called
-‘universal function call syntax’, and it looks like this:
-
-```rust
-# trait Foo {
-#     fn f(&self);
-# }
-# trait Bar {
-#     fn f(&self);
-# }
-# struct Baz;
-# impl Foo for Baz {
-#     fn f(&self) { println!("Baz’s impl of Foo"); }
-# }
-# impl Bar for Baz {
-#     fn f(&self) { println!("Baz’s impl of Bar"); }
-# }
-# let b = Baz;
-Foo::f(&b);
-Bar::f(&b);
-```
-
-Let’s break it down.
-
-```rust,ignore
-Foo::
-Bar::
-```
-
-These halves of the invocation are the types of the two traits: `Foo` and
-`Bar`. This is what ends up actually doing the disambiguation between the two:
-Rust calls the one from the trait name you use.
-
-```rust,ignore
-f(&b)
-```
-
-When we call a method like `b.f()` using [method syntax][methodsyntax], Rust
-will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will
-not, and so we need to pass an explicit `&b`.
-
-[methodsyntax]: method-syntax.html
-
-# Angle-bracket Form
-
-The form of UFCS we just talked about:
-
-```rust,ignore
-Trait::method(args);
-```
-
-Is a short-hand. There’s an expanded form of this that’s needed in some
-situations:
-
-```rust,ignore
-<Type as Trait>::method(args);
-```
-
-The `<>::` syntax is a means of providing a type hint. The type goes inside
-the `<>`s. In this case, the type is `Type as Trait`, indicating that we want
-`Trait`’s version of `method` to be called here. The `as Trait` part is
-optional if it’s not ambiguous. Same with the angle brackets, hence the
-shorter form.
-
-Here’s an example of using the longer form.
-
-```rust
-trait Foo {
-    fn foo() -> i32;
-}
-
-struct Bar;
-
-impl Bar {
-    fn foo() -> i32 {
-        20
-    }
-}
-
-impl Foo for Bar {
-    fn foo() -> i32 {
-        10
-    }
-}
-
-fn main() {
-    assert_eq!(10, <Bar as Foo>::foo());
-    assert_eq!(20, Bar::foo());
-}
-```
-
-Using the angle bracket syntax lets you call the trait method instead of the
-inherent one.
diff --git a/src/doc/book/src/unsafe.md b/src/doc/book/src/unsafe.md
deleted file mode 100644 (file)
index 9bf59fe..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-# Unsafe
-
-Rust’s main draw is its powerful static guarantees about behavior. But safety
-checks are conservative by nature: there are some programs that are actually
-safe, but the compiler is not able to verify this is true. To write these kinds
-of programs, we need to tell the compiler to relax its restrictions a bit. For
-this, Rust has a keyword, `unsafe`. Code using `unsafe` has fewer restrictions
-than normal code does.
-
-Let’s go over the syntax, and then we’ll talk semantics. `unsafe` is used in
-four contexts. The first one is to mark a function as unsafe:
-
-```rust
-unsafe fn danger_will_robinson() {
-    // Scary stuff...
-}
-```
-
-All functions called from [FFI][ffi] must be marked as `unsafe`, for example.
-The second use of `unsafe` is an unsafe block:
-
-[ffi]: ffi.html
-
-```rust
-unsafe {
-    // Scary stuff...
-}
-```
-
-The third is for unsafe traits:
-
-```rust
-unsafe trait Scary { }
-```
-
-And the fourth is for `impl`ementing one of those traits:
-
-```rust
-# unsafe trait Scary { }
-unsafe impl Scary for i32 {}
-```
-
-It’s important to be able to explicitly delineate code that may have bugs that
-cause big problems. If a Rust program segfaults, you can be sure the cause is
-related to something marked `unsafe`.
-
-# What does ‘safe’ mean?
-
-Safe, in the context of Rust, means ‘doesn’t do anything unsafe’. It’s also
-important to know that there are certain behaviors that are probably not
-desirable in your code, but are expressly _not_ unsafe:
-
-* Deadlocks
-* Leaks of memory or other resources
-* Exiting without calling destructors
-* Integer overflow
-
-Rust cannot prevent all kinds of software problems. Buggy code can and will be
-written in Rust. These things aren’t great, but they don’t qualify as `unsafe`
-specifically.
-
-In addition, the following are all undefined behaviors in Rust, and must be
-avoided, even when writing `unsafe` code:
-
-* Data races
-* Dereferencing a NULL/dangling raw pointer
-* Reads of [undef][undef] (uninitialized) memory
-* Breaking the [pointer aliasing rules][aliasing] with raw pointers.
-* `&mut T` and `&T` follow LLVM’s scoped [noalias][noalias] model, except if
-  the `&T` contains an `UnsafeCell<U>`. Unsafe code must not violate these
-  aliasing guarantees.
-* Mutating an immutable value/reference without `UnsafeCell<U>`
-* Invoking undefined behavior via compiler intrinsics:
-  * Indexing outside of the bounds of an object with `std::ptr::offset`
-    (`offset` intrinsic), with
-    the exception of one byte past the end which is permitted.
-  * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
-    intrinsics) on overlapping buffers
-* Invalid values in primitive types, even in private fields/locals:
-  * NULL/dangling references or boxes
-  * A value other than `false` (0) or `true` (1) in a `bool`
-  * A discriminant in an `enum` not included in its type definition
-  * A value in a `char` which is a surrogate or above `char::MAX`
-  * Non-UTF-8 byte sequences in a `str`
-* Unwinding into Rust from foreign code or unwinding from Rust into foreign
-  code.
-
-[noalias]: http://llvm.org/docs/LangRef.html#noalias
-[undef]: http://llvm.org/docs/LangRef.html#undefined-values
-[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules
-
-# Unsafe Superpowers
-
-In both unsafe functions and unsafe blocks, Rust will let you do three things
-that you normally can not do. Just three. Here they are:
-
-1. Access or update a [static mutable variable][static].
-2. Dereference a raw pointer.
-3. Call unsafe functions. This is the most powerful ability.
-
-That’s it. It’s important that `unsafe` does not, for example, ‘turn off the
-borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its
-semantics, it won’t start accepting anything. But it will let you write
-things that _do_ break some of the rules.
-
-You will also encounter the `unsafe` keyword when writing bindings to foreign
-(non-Rust) interfaces. You're encouraged to write a safe, native Rust interface
-around the methods provided by the library.
-
-Let’s go over the basic three abilities listed, in order.
-
-## Access or update a `static mut`
-
-Rust has a feature called ‘`static mut`’ which allows for mutable global state.
-Doing so can cause a data race, and as such is inherently not safe. For more
-details, see the [static][static] section of the book.
-
-[static]: const-and-static.html#static
-
-## Dereference a raw pointer
-
-Raw pointers let you do arbitrary pointer arithmetic, and can cause a number of
-different memory safety and security issues. In some senses, the ability to
-dereference an arbitrary pointer is one of the most dangerous things you can
-do. For more on raw pointers, see [their section of the book][rawpointers].
-
-[rawpointers]: raw-pointers.html
-
-## Call unsafe functions
-
-This last ability works with both aspects of `unsafe`: you can only call
-functions marked `unsafe` from inside an unsafe block.
-
-This ability is powerful and varied. Rust exposes some [compiler
-intrinsics][intrinsics] as unsafe functions, and some unsafe functions bypass
-safety checks, trading safety for speed.
-
-I’ll repeat again: even though you _can_ do arbitrary things in unsafe blocks
-and functions doesn’t mean you should. The compiler will act as though you’re
-upholding its invariants, so be careful!
-
-[intrinsics]: ../unstable-book/intrinsics.html
diff --git a/src/doc/book/src/unsized-types.md b/src/doc/book/src/unsized-types.md
deleted file mode 100644 (file)
index 2d09092..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-# Unsized Types
-
-Most types have a particular size, in bytes, that is knowable at compile time.
-For example, an `i32` is thirty-two bits big, or four bytes. However, there are
-some types which are useful to express, but do not have a defined size. These are
-called ‘unsized’ or ‘dynamically sized’ types. One example is `[T]`. This type
-represents a certain number of `T` in sequence. But we don’t know how many
-there are, so the size is not known.
-
-Rust understands a few of these types, but they have some restrictions. There
-are three:
-
-1. We can only manipulate an instance of an unsized type via a pointer. An
-   `&[T]` works fine, but a `[T]` does not.
-2. Variables and arguments cannot have dynamically sized types.
-3. Only the last field in a `struct` may have a dynamically sized type; the
-   other fields must not. Enum variants must not have dynamically sized types as
-   data.
-
-So why bother? Well, because `[T]` can only be used behind a pointer, if we
-didn’t have language support for unsized types, it would be impossible to write
-this:
-
-```rust,ignore
-impl Foo for str {
-```
-
-or
-
-```rust,ignore
-impl<T> Foo for [T] {
-```
-
-Instead, you would have to write:
-
-```rust,ignore
-impl Foo for &str {
-```
-
-Meaning, this implementation would only work for [references][ref], and not
-other types of pointers. With the `impl for str`, all pointers, including (at
-some point, there are some bugs to fix first) user-defined custom smart
-pointers, can use this `impl`.
-
-[ref]: references-and-borrowing.html
-
-# ?Sized
-
-If you want to write a function that accepts a dynamically sized type, you
-can use the special bound syntax, `?Sized`:
-
-```rust
-struct Foo<T: ?Sized> {
-    f: T,
-}
-```
-
-This `?Sized`, read as “T may or may not be `Sized`”, which allows us to match
-both sized and unsized types. All generic type parameters implicitly
-have the `Sized` bound, so the `?Sized` can be used to opt-out of the implicit
-bound.
diff --git a/src/doc/book/src/using-rust-without-the-standard-library.md b/src/doc/book/src/using-rust-without-the-standard-library.md
deleted file mode 100644 (file)
index 709d10f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# Using Rust Without the Standard Library
-
-Rust’s standard library provides a lot of useful functionality, but assumes
-support for various features of its host system: threads, networking, heap
-allocation, and others. There are systems that do not have these features,
-however, and Rust can work with those too! To do so, we tell Rust that we
-don’t want to use the standard library via an attribute: `#![no_std]`.
-
-> Note: This feature is technically stable, but there are some caveats. For
-> one, you can build a `#![no_std]` _library_ on stable, but not a _binary_.
-> For details on binaries without the standard library, see [the nightly
-> chapter on 'lang items'](../unstable-book/lang-items.html#using-libc)
-
-To use `#![no_std]`, add it to your crate root:
-
-```rust,ignore
-#![no_std]
-
-fn plus_one(x: i32) -> i32 {
-    x + 1
-}
-```
-
-Much of the functionality that’s exposed in the standard library is also
-available via the [`core` crate](../core/index.html). When we’re using the
-standard library, Rust automatically brings `std` into scope, allowing you to
-use its features without an explicit import. By the same token, when using
-`#![no_std]`, Rust will bring `core` into scope for you, as well as [its
-prelude](../core/prelude/v1/index.html). This means that a lot of code will Just
-Work:
-
-```rust,ignore
-#![no_std]
-
-fn may_fail(failure: bool) -> Result<(), &'static str> {
-    if failure {
-        Err("this didn’t work!")
-    } else {
-        Ok(())
-    }
-}
-```
diff --git a/src/doc/book/src/variable-bindings.md b/src/doc/book/src/variable-bindings.md
deleted file mode 100644 (file)
index d6aa8b1..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-# Variable Bindings
-
-Virtually every non-'Hello World’ Rust program uses *variable bindings*. They
-bind some value to a name, so it can be used later. `let` is
-used to introduce a binding, like this:
-
-```rust
-fn main() {
-    let x = 5;
-}
-```
-
-Putting `fn main() {` in each example is a bit tedious, so we’ll leave that out
-in the future. If you’re following along, make sure to edit your `main()`
-function, rather than leaving it off. Otherwise, you’ll get an error.
-
-# Patterns
-
-In many languages, a variable binding would be called a *variable*, but Rust’s
-variable bindings have a few tricks up their sleeves. For example the
-left-hand side of a `let` statement is a ‘[pattern][pattern]’, not a
-variable name. This means we can do things like:
-
-```rust
-let (x, y) = (1, 2);
-```
-
-After this statement is evaluated, `x` will be one, and `y` will be two.
-Patterns are really powerful, and have [their own section][pattern] in the
-book. We don’t need those features for now, so we’ll keep this in the back
-of our minds as we go forward.
-
-[pattern]: patterns.html
-
-# Type annotations
-
-Rust is a statically typed language, which means that we specify our types up
-front, and they’re checked at compile time. So why does our first example
-compile? Well, Rust has this thing called ‘type inference’. If it can figure
-out what the type of something is, Rust doesn’t require you to explicitly type
-it out.
-
-We can add the type if we want to, though. Types come after a colon (`:`):
-
-```rust
-let x: i32 = 5;
-```
-
-If I asked you to read this out loud to the rest of the class, you’d say “`x`
-is a binding with the type `i32` and the value `5`.”
-
-In this case we chose to represent `x` as a 32-bit signed integer. Rust has
-many different primitive integer types. They begin with `i` for signed integers
-and `u` for unsigned integers. The possible integer sizes are 8, 16, 32, and 64
-bits.
-
-In future examples, we may annotate the type in a comment. The examples will
-look like this:
-
-```rust
-fn main() {
-    let x = 5; // x: i32
-}
-```
-
-Note the similarities between this annotation and the syntax you use with
-`let`. Including these kinds of comments is not idiomatic Rust, but we'll
-occasionally include them to help you understand what the types that Rust
-infers are.
-
-# Mutability
-
-By default, bindings are *immutable*. This code will not compile:
-
-```rust,ignore
-let x = 5;
-x = 10;
-```
-
-It will give you this error:
-
-```text
-error: re-assignment of immutable variable `x`
-     x = 10;
-     ^~~~~~~
-```
-
-If you want a binding to be mutable, you can use `mut`:
-
-```rust
-let mut x = 5; // mut x: i32
-x = 10;
-```
-
-There is no single reason that bindings are immutable by default, but we can
-think about it through one of Rust’s primary focuses: safety. If you forget to
-say `mut`, the compiler will catch it, and let you know that you have mutated
-something you may not have intended to mutate. If bindings were mutable by
-default, the compiler would not be able to tell you this. If you _did_ intend
-mutation, then the solution is quite easy: add `mut`.
-
-There are other good reasons to avoid mutable state when possible, but they’re
-out of the scope of this guide. In general, you can often avoid explicit
-mutation, and so it is preferable in Rust. That said, sometimes, mutation is
-what you need, so it’s not forbidden.
-
-# Initializing bindings
-
-Rust variable bindings have one more aspect that differs from other languages:
-bindings are required to be initialized with a value before you're allowed to
-use them.
-
-Let’s try it out. Change your `src/main.rs` file to look like this:
-
-```rust
-fn main() {
-    let x: i32;
-
-    println!("Hello world!");
-}
-```
-
-You can use `cargo build` on the command line to build it. You’ll get a
-warning, but it will still print "Hello, world!":
-
-```text
-   Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
-src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variables)]
-   on by default
-src/main.rs:2     let x: i32;
-                      ^
-```
-
-Rust warns us that we never use the variable binding, but since we never use
-it, no harm, no foul. Things change if we try to actually use this `x`,
-however. Let’s do that. Change your program to look like this:
-
-```rust,ignore
-fn main() {
-    let x: i32;
-
-    println!("The value of x is: {}", x);
-}
-```
-
-And try to build it. You’ll get an error:
-
-```bash
-$ cargo build
-   Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
-src/main.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x`
-src/main.rs:4     println!("The value of x is: {}", x);
-                                                    ^
-note: in expansion of format_args!
-<std macros>:2:23: 2:77 note: expansion site
-<std macros>:1:1: 3:2 note: in expansion of println!
-src/main.rs:4:5: 4:42 note: expansion site
-error: aborting due to previous error
-Could not compile `hello_world`.
-```
-
-Rust will not let us use a value that has not been initialized.
-
-Let us take a minute to talk about this stuff we've added to `println!`.
-
-If you include two curly braces (`{}`, some call them moustaches...) in your
-string to print, Rust will interpret this as a request to interpolate some sort
-of value. *String interpolation* is a computer science term that means "stick
-in the middle of a string." We add a comma, and then `x`, to indicate that we
-want `x` to be the value we’re interpolating. The comma is used to separate
-arguments we pass to functions and macros, if you’re passing more than one.
-
-When you use the curly braces, Rust will attempt to display the value in a
-meaningful way by checking out its type. If you want to specify the format in a
-more detailed manner, there are a [wide number of options available][format].
-For now, we'll stick to the default: integers aren't very complicated to
-print.
-
-[format]: ../std/fmt/index.html
-
-# Scope and shadowing
-
-Let’s get back to bindings. Variable bindings have a scope - they are
-constrained to live in the block they were defined in. A block is a collection
-of statements enclosed by `{` and `}`. Function definitions are also blocks!
-In the following example we define two variable bindings, `x` and `y`, which
-live in different blocks. `x` can be accessed from inside the `fn main() {}`
-block, while `y` can be accessed only from inside the inner block:
-
-```rust,ignore
-fn main() {
-    let x: i32 = 17;
-    {
-        let y: i32 = 3;
-        println!("The value of x is {} and value of y is {}", x, y);
-    }
-    println!("The value of x is {} and value of y is {}", x, y); // This won't work.
-}
-```
-
-The first `println!` would print "The value of x is 17 and the value of y is
-3", but this example cannot be compiled successfully, because the second
-`println!` cannot access the value of `y`, since it is not in scope anymore.
-Instead we get this error:
-
-```bash
-$ cargo build
-   Compiling hello v0.1.0 (file:///home/you/projects/hello_world)
-main.rs:7:62: 7:63 error: unresolved name `y`. Did you mean `x`? [E0425]
-main.rs:7     println!("The value of x is {} and value of y is {}", x, y); // This won't work.
-                                                                       ^
-note: in expansion of format_args!
-<std macros>:2:25: 2:56 note: expansion site
-<std macros>:1:1: 2:62 note: in expansion of print!
-<std macros>:3:1: 3:54 note: expansion site
-<std macros>:1:1: 3:58 note: in expansion of println!
-main.rs:7:5: 7:65 note: expansion site
-main.rs:7:62: 7:63 help: run `rustc --explain E0425` to see a detailed explanation
-error: aborting due to previous error
-Could not compile `hello`.
-
-To learn more, run the command again with --verbose.
-```
-
-Additionally, variable bindings can be shadowed. This means that a later
-variable binding with the same name as another binding that is currently in
-scope will override the previous binding.
-
-```rust
-let x: i32 = 8;
-{
-    println!("{}", x); // Prints "8".
-    let x = 12;
-    println!("{}", x); // Prints "12".
-}
-println!("{}", x); // Prints "8".
-let x =  42;
-println!("{}", x); // Prints "42".
-```
-
-Shadowing and mutable bindings may appear as two sides of the same coin, but
-they are two distinct concepts that can't always be used interchangeably. For
-one, shadowing enables us to rebind a name to a value of a different type. It
-is also possible to change the mutability of a binding. Note that shadowing a 
-name does not alter or destroy the value it was bound to, and the value will
-continue to exist until it goes out of scope, even if it is no longer accessible
-by any means.
-
-```rust
-let mut x: i32 = 1;
-x = 7;
-let x = x; // `x` is now immutable and is bound to `7`.
-
-let y = 4;
-let y = "I can also be bound to text!"; // `y` is now of a different type.
-```
diff --git a/src/doc/book/src/vectors.md b/src/doc/book/src/vectors.md
deleted file mode 100644 (file)
index aff0787..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-# Vectors
-
-A ‘vector’ is a dynamic or ‘growable’ array, implemented as the standard
-library type [`Vec<T>`][vec]. The `T` means that we can have vectors
-of any type (see the chapter on [generics][generic] for more).
-Vectors always allocate their data on the heap.
-You can create them with the `vec!` macro:
-
-```rust
-let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32>
-```
-
-(Notice that unlike the `println!` macro we’ve used in the past, we use square
-brackets `[]` with `vec!` macro. Rust allows you to use either in either
-situation, this is just convention.)
-
-There’s an alternate form of `vec!` for repeating an initial value:
-
-```rust
-let v = vec![0; 10]; // A vector of ten zeroes.
-```
-
-Vectors store their contents as contiguous arrays of `T` on the heap. This means
-that they must be able to know the size of `T` at compile time (that is, how
-many bytes are needed to store a `T`?). The size of some things can't be known
-at compile time. For these you'll have to store a pointer to that thing:
-thankfully, the [`Box`][box] type works perfectly for this.
-
-## Accessing elements
-
-To get the value at a particular index in the vector, we use `[]`s:
-
-```rust
-let v = vec![1, 2, 3, 4, 5];
-
-println!("The third element of v is {}", v[2]);
-```
-
-The indices count from `0`, so the third element is `v[2]`.
-
-It’s also important to note that you must index with the `usize` type:
-
-```rust,ignore
-let v = vec![1, 2, 3, 4, 5];
-
-let i: usize = 0;
-let j: i32 = 0;
-
-// Works:
-v[i];
-
-// Doesn’t:
-v[j];
-```
-
-Indexing with a non-`usize` type gives an error that looks like this:
-
-```text
-error: the trait bound `collections::vec::Vec<_> : core::ops::Index<i32>`
-is not satisfied [E0277]
-v[j];
-^~~~
-note: the type `collections::vec::Vec<_>` cannot be indexed by `i32`
-error: aborting due to previous error
-```
-
-There’s a lot of punctuation in that message, but the core of it makes sense:
-you cannot index with an `i32`.
-
-## Out-of-bounds Access
-
-If you try to access an index that doesn’t exist:
-
-```rust,ignore
-let v = vec![1, 2, 3];
-println!("Item 7 is {}", v[7]);
-```
-
-then the current thread will [panic] with a message like this:
-
-```text
-thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 7'
-```
-
-If you want to handle out-of-bounds errors without panicking, you can use
-methods like [`get`][get] or [`get_mut`][get_mut] that return `None` when
-given an invalid index:
-
-```rust
-let v = vec![1, 2, 3];
-match v.get(7) {
-    Some(x) => println!("Item 7 is {}", x),
-    None => println!("Sorry, this vector is too short.")
-}
-```
-
-## Iterating
-
-Once you have a vector, you can iterate through its elements with `for`. There
-are three versions:
-
-```rust
-let mut v = vec![1, 2, 3, 4, 5];
-
-for i in &v {
-    println!("A reference to {}", i);
-}
-
-for i in &mut v {
-    println!("A mutable reference to {}", i);
-}
-
-for i in v {
-    println!("Take ownership of the vector and its element {}", i);
-}
-```
-
-Note: You cannot use the vector again once you have iterated by taking ownership of the vector.
-You can iterate the vector multiple times by taking a reference to the vector whilst iterating.
-For example, the following code does not compile.
-
-```rust,ignore
-let v = vec![1, 2, 3, 4, 5];
-
-for i in v {
-    println!("Take ownership of the vector and its element {}", i);
-}
-
-for i in v {
-    println!("Take ownership of the vector and its element {}", i);
-}
-```
-
-Whereas the following works perfectly,
-
-```rust
-let v = vec![1, 2, 3, 4, 5];
-
-for i in &v {
-    println!("This is a reference to {}", i);
-}
-
-for i in &v {
-    println!("This is a reference to {}", i);
-}
-```
-
-Vectors have many more useful methods, which you can read about in [their
-API documentation][vec].
-
-[vec]: ../std/vec/index.html
-[box]: ../std/boxed/index.html
-[generic]: generics.html
-[panic]: concurrency.html#panics
-[get]: ../std/vec/struct.Vec.html#method.get
-[get_mut]: ../std/vec/struct.Vec.html#method.get_mut
index 2d23ea601f017c106a2303094ee1c57ba856d246..516549972d61c8946542d1a34afeae97167ff77b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2d23ea601f017c106a2303094ee1c57ba856d246
+Subproject commit 516549972d61c8946542d1a34afeae97167ff77b
index 7820d44920829fe6e3dc1657fc9e8a5e95b361a0..456c76d43a6ece8d318d19adb2347806ddd80c42 100644 (file)
@@ -65,7 +65,6 @@
 - [plugin_registrar](plugin-registrar.md)
 - [prelude_import](prelude-import.md)
 - [proc_macro](proc-macro.md)
-- [pub_restricted](pub-restricted.md)
 - [quote](quote.md)
 - [relaxed_adts](relaxed-adts.md)
 - [repr_simd](repr-simd.md)
index ca69b7084d3e64b903beb8d8674f90a096786c24..3a1872e18ddb8a6968594016964fa4f8a5569522 100644 (file)
@@ -137,7 +137,7 @@ of extensions.  See `Registry::register_syntax_extension` and the
 
 ## Tips and tricks
 
-Some of the [macro debugging tips](../book/macros.html#debugging-macro-code) are applicable.
+Some of the [macro debugging tips](../book/first-edition/macros.html#debugging-macro-code) are applicable.
 
 You can use `syntax::parse` to turn token trees into
 higher-level syntax elements like expressions:
diff --git a/src/doc/unstable-book/src/pub-restricted.md b/src/doc/unstable-book/src/pub-restricted.md
deleted file mode 100644 (file)
index 7304618..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# `pub_restricted`
-
-The tracking issue for this feature is: [#32409]
-
-[#32409]: https://github.com/rust-lang/rust/issues/32409
-
-------------------------
-
-
-
index 1d616233881b4bb955247d17304323bed0e7d4e0..28f6d97756f2c4c0f2808d49de7b461edf7ec876 100644 (file)
 /// [downgrade]: struct.Arc.html#method.downgrade
 /// [upgrade]: struct.Weak.html#method.upgrade
 /// [`None`]: ../../std/option/enum.Option.html#variant.None
-/// [assoc]: ../../book/method-syntax.html#associated-functions
+/// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions
 ///
 /// # Examples
 ///
index e9b59017692eb3907747cb5d3874215823c44e8f..561ccaa5ef5ca6c0c8f4e78c58591b7bdd4cfc4b 100644 (file)
 //! [downgrade]: struct.Rc.html#method.downgrade
 //! [upgrade]: struct.Weak.html#method.upgrade
 //! [`None`]: ../../std/option/enum.Option.html#variant.None
-//! [assoc]: ../../book/method-syntax.html#associated-functions
+//! [assoc]: ../../book/first-edition/method-syntax.html#associated-functions
 //! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable
 
 #![stable(feature = "rust1", since = "1.0.0")]
index 1ec1749c3aa64eb09eeee26cbb1383c030e4a448..62a88164621913fd494c67488ce5f1c720dada64 100644 (file)
 //!         like `{:08}` would yield `00000001` for the integer `1`, while the
 //!         same format would yield `-0000001` for the integer `-1`. Notice that
 //!         the negative version has one fewer zero than the positive version.
+//!         Note that padding zeroes are always placed after the sign (if any)
+//!         and before the digits. When used together with the `#` flag, a similar
+//!         rule applies: padding zeroes are inserted after the prefix but before
+//!         the digits.
 //!
 //! ## Width
 //!
index fb42b915c7694a542957d62ea0575f4d38e3c372..58aba11e4394f6e619c60775d353cb0df68b35c8 100644 (file)
@@ -34,8 +34,8 @@ pub mod reimpls {
     macro_rules! ashl {
         ($a:expr, $b:expr, $ty:ty) => {{
             let (a, b) = ($a, $b);
-            let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
-            let half_bits = bits >> 1;
+            let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
+            let half_bits = bits.wrapping_shr(1);
             if b & half_bits != 0 {
                 <$ty>::from_parts(0, a.low().wrapping_shl(
                                         b.wrapping_sub(half_bits) as u32))
@@ -58,8 +58,8 @@ pub extern "C" fn shl(a: u128, b: u128) -> u128 {
     macro_rules! ashr {
         ($a: expr, $b: expr, $ty:ty) => {{
             let (a, b) = ($a, $b);
-            let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
-            let half_bits = bits >> 1;
+            let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
+            let half_bits = bits.wrapping_shr(1);
             if b & half_bits != 0 {
                 <$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32)
                                   as <$ty as LargeInt>::LowHalf,
@@ -83,8 +83,8 @@ pub extern "C" fn shr(a: i128, b: i128) -> i128 {
     macro_rules! lshr {
         ($a: expr, $b: expr, $ty:ty) => {{
             let (a, b) = ($a, $b);
-            let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
-            let half_bits = bits >> 1;
+            let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
+            let half_bits = bits.wrapping_shr(1);
             if b & half_bits != 0 {
                 <$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32), 0)
             } else if b == 0 {
@@ -370,7 +370,7 @@ fn from_parts(low: u64, high: i64) -> i128 {
     macro_rules! mul {
         ($a:expr, $b:expr, $ty: ty, $tyh: ty) => {{
             let (a, b) = ($a, $b);
-            let half_bits = ((::core::mem::size_of::<$tyh>() * 8) / 2) as u32;
+            let half_bits = ::core::mem::size_of::<$tyh>().wrapping_mul(4) as u32;
             let lower_mask = (!0u64).wrapping_shr(half_bits);
             let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask);
             let mut t = low.wrapping_shr(half_bits);
@@ -478,7 +478,7 @@ macro_rules! float_as_unsigned {
             let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
             let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
             if sign == -1.0 || exponent < 0 { return 0 as u128; }
-            if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
+            if exponent > ::core::mem::size_of::<$outty>().wrapping_mul(8) as i32 {
                 return !(0 as u128);
             }
             (if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
@@ -503,7 +503,7 @@ macro_rules! float_as_signed {
             let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
 
             if exponent < 0 { return 0 as i128; }
-            if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
+            if exponent > ::core::mem::size_of::<$outty>().wrapping_mul(8) as i32 {
                 let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() };
                 return ret
             }
index 649fdf394e422bf3eec8add5b3c1f7d835c0e0c3..19e69ca296d8f4ea5221c0d9a6b45fb5e7f0c4f8 100644 (file)
@@ -94,7 +94,7 @@
 ///
 /// [`char`]: ../../std/primitive.char.html
 /// [`u32`]: ../../std/primitive.u32.html
-/// [`as`]: ../../book/casting-between-types.html#as
+/// [`as`]: ../../book/first-edition/casting-between-types.html#as
 ///
 /// For an unsafe version of this function which ignores these checks, see
 /// [`from_u32_unchecked`].
@@ -146,7 +146,7 @@ pub fn from_u32(i: u32) -> Option<char> {
 ///
 /// [`char`]: ../../std/primitive.char.html
 /// [`u32`]: ../../std/primitive.u32.html
-/// [`as`]: ../../book/casting-between-types.html#as
+/// [`as`]: ../../book/first-edition/casting-between-types.html#as
 ///
 /// # Safety
 ///
index 1657342ff6ac6f8aa567307edc13e9c727147309..0bfab92fa5d5180270491af1fb3e8320b9587da0 100644 (file)
@@ -1045,6 +1045,7 @@ pub fn pad_integral(&mut self,
             // is zero
             Some(min) if self.sign_aware_zero_pad() => {
                 self.fill = '0';
+                self.align = rt::v1::Alignment::Right;
                 write_prefix(self)?;
                 self.with_padding(min - width, rt::v1::Alignment::Right, |f| {
                     f.buf.write_str(buf)
@@ -1153,8 +1154,9 @@ fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result {
             // for the sign-aware zero padding, we render the sign first and
             // behave as if we had no sign from the beginning.
             let mut formatted = formatted.clone();
-            let mut align = self.align;
             let old_fill = self.fill;
+            let old_align = self.align;
+            let mut align = old_align;
             if self.sign_aware_zero_pad() {
                 // a sign always goes first
                 let sign = unsafe { str::from_utf8_unchecked(formatted.sign) };
@@ -1165,6 +1167,7 @@ fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result {
                 width = if width < sign.len() { 0 } else { width - sign.len() };
                 align = rt::v1::Alignment::Right;
                 self.fill = '0';
+                self.align = rt::v1::Alignment::Right;
             }
 
             // remaining parts go through the ordinary padding process.
@@ -1177,6 +1180,7 @@ fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result {
                 })
             };
             self.fill = old_fill;
+            self.align = old_align;
             ret
         } else {
             // this is the common case and we take a shortcut
index 12410c08f399b3f059126492196bda0e807d886d..1ae8b6bb45113b45a491d5868a059de76d799691 100644 (file)
             issue = "0")]
 #![allow(missing_docs)]
 
-extern "rust-intrinsic" {
+#[cfg(not(stage0))]
+#[stable(feature = "drop_in_place", since = "1.8.0")]
+#[rustc_deprecated(reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
+                   since = "1.18.0")]
+pub use ptr::drop_in_place;
 
+extern "rust-intrinsic" {
     // NB: These intrinsics take raw pointers because they mutate aliased
     // memory, which is not valid for either `&` or `&mut`.
 
     pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
     pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
 
+    #[cfg(stage0)]
     /// Executes the destructor (if any) of the pointed-to value.
     ///
     /// This has two use cases:
@@ -1238,6 +1244,15 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
     pub fn unchecked_rem<T>(x: T, y: T) -> T;
 
+    /// Performs an unchecked left shift, resulting in undefined behavior when
+    /// y < 0 or y >= N, where N is the width of T in bits.
+    #[cfg(not(stage0))]
+    pub fn unchecked_shl<T>(x: T, y: T) -> T;
+    /// Performs an unchecked right shift, resulting in undefined behavior when
+    /// y < 0 or y >= N, where N is the width of T in bits.
+    #[cfg(not(stage0))]
+    pub fn unchecked_shr<T>(x: T, y: T) -> T;
+
     /// Returns (a + b) mod 2^N, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_add` method. For example,
index 1301c311c14caa361f22bb6471cb9b492cc76dc1..fb98e43aa614b302f0ddf9707ebbaecde04585f1 100644 (file)
@@ -409,7 +409,7 @@ fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> where
     /// If you're doing some sort of looping for a side effect, it's considered
     /// more idiomatic to use [`for`] than `map()`.
     ///
-    /// [`for`]: ../../book/loops.html#for
+    /// [`for`]: ../../book/first-edition/loops.html#for
     ///
     /// # Examples
     ///
@@ -1306,7 +1306,7 @@ fn partition<B, F>(self, mut f: F) -> (B, B) where
     /// use a `for` loop with a list of things to build up a result. Those
     /// can be turned into `fold()`s:
     ///
-    /// [`for`]: ../../book/loops.html#for
+    /// [`for`]: ../../book/first-edition/loops.html#for
     ///
     /// ```
     /// let numbers = [1, 2, 3, 4, 5];
index ba65e4494a8bbed54cb47b242d3b3161265b4c36..f5cf3724d0711d8183e685a02d08878f37ad3e95 100644 (file)
 /// [uninit]: fn.uninitialized.html
 /// [clone]: ../clone/trait.Clone.html
 /// [swap]: fn.swap.html
-/// [FFI]: ../../book/ffi.html
+/// [FFI]: ../../book/first-edition/ffi.html
 /// [box]: ../../std/boxed/struct.Box.html
 /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
 /// [ub]: ../../reference/behavior-considered-undefined.html
@@ -199,7 +199,7 @@ pub fn size_of<T>() -> usize {
 /// then `size_of_val` can be used to get the dynamically-known size.
 ///
 /// [slice]: ../../std/primitive.slice.html
-/// [trait object]: ../../book/trait-objects.html
+/// [trait object]: ../../book/first-edition/trait-objects.html
 ///
 /// # Examples
 ///
@@ -317,7 +317,7 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
 /// many of the same caveats.
 ///
 /// [uninit]: fn.uninitialized.html
-/// [FFI]: ../../book/ffi.html
+/// [FFI]: ../../book/first-edition/ffi.html
 /// [ub]: ../../reference/behavior-considered-undefined.html
 ///
 /// # Examples
@@ -343,7 +343,7 @@ pub unsafe fn zeroed<T>() -> T {
 /// This is useful for [FFI] functions and initializing arrays sometimes,
 /// but should generally be avoided.
 ///
-/// [FFI]: ../../book/ffi.html
+/// [FFI]: ../../book/first-edition/ffi.html
 ///
 /// # Undefined behavior
 ///
@@ -525,7 +525,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 /// it will not release any borrows, as borrows are based on lexical scope.
 ///
 /// This effectively does nothing for
-/// [types which implement `Copy`](../../book/ownership.html#copy-types),
+/// [types which implement `Copy`](../../book/first-edition/ownership.html#copy-types),
 /// e.g. integers. Such values are copied and _then_ moved into the function,
 /// so the value persists after this function call.
 ///
index 13fa099c8eb01620c474ad8cd23fb1b694057b5e..ccfe6364e6af6785061d76fd31c0b02edef62d39 100644 (file)
@@ -177,7 +177,7 @@ macro_rules! checked_op {
 
 // `Int` + `SignedInt` implemented for signed integers
 macro_rules! int_impl {
-    ($ActualT:ident, $UnsignedT:ty, $BITS:expr,
+    ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr,
      $add_with_overflow:path,
      $sub_with_overflow:path,
      $mul_with_overflow:path) => {
@@ -850,6 +850,17 @@ pub fn wrapping_neg(self) -> Self {
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
+        #[cfg(not(stage0))]
+        pub fn wrapping_shl(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Stage 0
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline(always)]
+        #[cfg(stage0)]
         pub fn wrapping_shl(self, rhs: u32) -> Self {
             self.overflowing_shl(rhs).0
         }
@@ -875,6 +886,17 @@ pub fn wrapping_shl(self, rhs: u32) -> Self {
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
+        #[cfg(not(stage0))]
+        pub fn wrapping_shr(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Stage 0
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline(always)]
+        #[cfg(stage0)]
         pub fn wrapping_shr(self, rhs: u32) -> Self {
             self.overflowing_shr(rhs).0
         }
@@ -1089,6 +1111,15 @@ pub fn overflowing_neg(self) -> (Self, bool) {
         /// ```
         #[inline]
         #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(not(stage0))]
+        pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+        }
+
+        /// Stage 0
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(stage0)]
         pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
             (self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
@@ -1111,6 +1142,15 @@ pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
         /// ```
         #[inline]
         #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(not(stage0))]
+        pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+        }
+
+        /// Stage 0
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(stage0)]
         pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
             (self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
@@ -1268,7 +1308,7 @@ pub fn is_negative(self) -> bool { self < 0 }
 
 #[lang = "i8"]
 impl i8 {
-    int_impl! { i8, u8, 8,
+    int_impl! { i8, i8, u8, 8,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1276,7 +1316,7 @@ impl i8 {
 
 #[lang = "i16"]
 impl i16 {
-    int_impl! { i16, u16, 16,
+    int_impl! { i16, i16, u16, 16,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1284,7 +1324,7 @@ impl i16 {
 
 #[lang = "i32"]
 impl i32 {
-    int_impl! { i32, u32, 32,
+    int_impl! { i32, i32, u32, 32,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1292,7 +1332,7 @@ impl i32 {
 
 #[lang = "i64"]
 impl i64 {
-    int_impl! { i64, u64, 64,
+    int_impl! { i64, i64, u64, 64,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1300,7 +1340,7 @@ impl i64 {
 
 #[lang = "i128"]
 impl i128 {
-    int_impl! { i128, u128, 128,
+    int_impl! { i128, i128, u128, 128,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1309,7 +1349,7 @@ impl i128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { i16, u16, 16,
+    int_impl! { isize, i16, u16, 16,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1318,7 +1358,7 @@ impl isize {
 #[cfg(target_pointer_width = "32")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { i32, u32, 32,
+    int_impl! { isize, i32, u32, 32,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1327,7 +1367,7 @@ impl isize {
 #[cfg(target_pointer_width = "64")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { i64, u64, 64,
+    int_impl! { isize, i64, u64, 64,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1335,7 +1375,7 @@ impl isize {
 
 // `Int` + `UnsignedInt` implemented for unsigned integers
 macro_rules! uint_impl {
-    ($ActualT:ty, $BITS:expr,
+    ($SelfT:ty, $ActualT:ty, $BITS:expr,
      $ctpop:path,
      $ctlz:path,
      $cttz:path,
@@ -1978,6 +2018,17 @@ pub fn wrapping_neg(self) -> Self {
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
+        #[cfg(not(stage0))]
+        pub fn wrapping_shl(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Stage 0
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline(always)]
+        #[cfg(stage0)]
         pub fn wrapping_shl(self, rhs: u32) -> Self {
             self.overflowing_shl(rhs).0
         }
@@ -2003,6 +2054,17 @@ pub fn wrapping_shl(self, rhs: u32) -> Self {
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
+        #[cfg(not(stage0))]
+        pub fn wrapping_shr(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Stage 0
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline(always)]
+        #[cfg(stage0)]
         pub fn wrapping_shr(self, rhs: u32) -> Self {
             self.overflowing_shr(rhs).0
         }
@@ -2170,6 +2232,15 @@ pub fn overflowing_neg(self) -> (Self, bool) {
         /// ```
         #[inline]
         #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(not(stage0))]
+        pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+        }
+
+        /// Stage 0
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(stage0)]
         pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
             (self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
@@ -2192,6 +2263,16 @@ pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
         /// ```
         #[inline]
         #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(not(stage0))]
+        pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+
+        }
+
+        /// Stage 0
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(stage0)]
         pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
             (self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
@@ -2292,7 +2373,7 @@ pub fn checked_next_power_of_two(self) -> Option<Self> {
 
 #[lang = "u8"]
 impl u8 {
-    uint_impl! { u8, 8,
+    uint_impl! { u8, u8, 8,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2304,7 +2385,7 @@ impl u8 {
 
 #[lang = "u16"]
 impl u16 {
-    uint_impl! { u16, 16,
+    uint_impl! { u16, u16, 16,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2316,7 +2397,7 @@ impl u16 {
 
 #[lang = "u32"]
 impl u32 {
-    uint_impl! { u32, 32,
+    uint_impl! { u32, u32, 32,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2328,7 +2409,7 @@ impl u32 {
 
 #[lang = "u64"]
 impl u64 {
-    uint_impl! { u64, 64,
+    uint_impl! { u64, u64, 64,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2340,7 +2421,7 @@ impl u64 {
 
 #[lang = "u128"]
 impl u128 {
-    uint_impl! { u128, 128,
+    uint_impl! { u128, u128, 128,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2353,7 +2434,7 @@ impl u128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { u16, 16,
+    uint_impl! { usize, u16, 16,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2365,7 +2446,7 @@ impl usize {
 #[cfg(target_pointer_width = "32")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { u32, 32,
+    uint_impl! { usize, u32, 32,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2378,7 +2459,7 @@ impl usize {
 #[cfg(target_pointer_width = "64")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { u64, 64,
+    uint_impl! { usize, u64, 64,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
index 07a7d2f95b1f212a1d69dca4a7aefd38ddb50fc8..98544f8ba5e73d87dbd310ff6991fac06f7885b6 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use intrinsics::write_bytes;
 
+#[cfg(stage0)]
 #[stable(feature = "drop_in_place", since = "1.8.0")]
 pub use intrinsics::drop_in_place;
 
+#[cfg(not(stage0))]
+/// Executes the destructor (if any) of the pointed-to value.
+///
+/// This has two use cases:
+///
+/// * It is *required* to use `drop_in_place` to drop unsized types like
+///   trait objects, because they can't be read out onto the stack and
+///   dropped normally.
+///
+/// * It is friendlier to the optimizer to do this over `ptr::read` when
+///   dropping manually allocated memory (e.g. when writing Box/Rc/Vec),
+///   as the compiler doesn't need to prove that it's sound to elide the
+///   copy.
+///
+/// # Undefined Behavior
+///
+/// This has all the same safety problems as `ptr::read` with respect to
+/// invalid pointers, types, and double drops.
+#[stable(feature = "drop_in_place", since = "1.8.0")]
+#[lang="drop_in_place"]
+#[inline]
+#[allow(unconditional_recursion)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+    // Code here does not matter - this is replaced by the
+    // real drop glue by the compiler.
+    drop_in_place(to_drop);
+}
+
 /// Creates a null raw pointer.
 ///
 /// # Examples
index a7d0d3899b181d2dd3add95f7bbb46c2bb83ced3..a95f05227fb8b1b38ef596cdacaae5744569c1f7 100644 (file)
@@ -25,7 +25,7 @@
 /// Book][moreinfo] contains more details about the precise nature of
 /// these internals.
 ///
-/// [moreinfo]: ../../book/trait-objects.html#representation
+/// [moreinfo]: ../../book/first-edition/trait-objects.html#representation
 ///
 /// `TraitObject` is guaranteed to match layouts, but it is not the
 /// type of trait objects (e.g. the fields are not directly accessible
index e904290957619cbb8f8d0c3d87f3c042c740e420..a6dad64125331cc4c6ab5d903615fffbe8be4389 100644 (file)
 //! A library for procedural macro writers.
 //!
 //! ## Usage
-//! This crate provides the `qquote!` macro for syntax creation.
+//! This crate provides the `quote!` macro for syntax creation.
 //!
-//! The `qquote!` macro uses the crate `syntax`, so users must declare `extern crate syntax;`
+//! The `quote!` macro uses the crate `syntax`, so users must declare `extern crate syntax;`
 //! at the crate root. This is a temporary solution until we have better hygiene.
 //!
 //! ## Quasiquotation
 //!
 //! The quasiquoter creates output that, when run, constructs the tokenstream specified as
-//! input. For example, `qquote!(5 + 5)` will produce a program, that, when run, will
+//! input. For example, `quote!(5 + 5)` will produce a program, that, when run, will
 //! construct the TokenStream `5 | + | 5`.
 //!
 //! ### Unquoting
 //!
-//! Unquoting is currently done as `unquote`, and works by taking the single next
-//! TokenTree in the TokenStream as the unquoted term. Ergonomically, `unquote(foo)` works
-//! fine, but `unquote foo` is also supported.
+//! Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
+//! To quote `$` itself, use `$$`.
 //!
-//! A simple example might be:
+//! A simple example is:
 //!
 //!```
 //!fn double(tmp: TokenStream) -> TokenStream {
-//!    qquote!(unquote(tmp) * 2)
+//!    quote!($tmp * 2)
 //!}
 //!```
 //!
-//! ### Large Example: Implementing Scheme's `cond`
+//! ### Large example: Scheme's `cond`
 //!
-//! Below is the full implementation of Scheme's `cond` operator.
+//! Below is an example implementation of Scheme's `cond`.
 //!
 //! ```
-//! fn cond_rec(input: TokenStream) -> TokenStream {
-//!   if input.is_empty() { return quote!(); }
-//!
-//!   let next = input.slice(0..1);
-//!   let rest = input.slice_from(1..);
-//!
-//!   let clause : TokenStream = match next.maybe_delimited() {
-//!     Some(ts) => ts,
-//!     _ => panic!("Invalid input"),
-//!   };
-//!
-//!   // clause is ([test]) [rhs]
-//!   if clause.len() < 2 { panic!("Invalid macro usage in cond: {:?}", clause) }
-//!
-//!   let test: TokenStream = clause.slice(0..1);
-//!   let rhs: TokenStream = clause.slice_from(1..);
-//!
-//!   if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
-//!     quote!({unquote(rhs)})
-//!   } else {
-//!     quote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
-//!   }
+//! fn cond(input: TokenStream) -> TokenStream {
+//!     let mut conds = Vec::new();
+//!     let mut input = input.trees().peekable();
+//!     while let Some(tree) = input.next() {
+//!         let mut cond = match tree {
+//!             TokenTree::Delimited(_, ref delimited) => delimited.stream(),
+//!             _ => panic!("Invalid input"),
+//!         };
+//!         let mut trees = cond.trees();
+//!         let test = trees.next();
+//!         let rhs = trees.collect::<TokenStream>();
+//!         if rhs.is_empty() {
+//!             panic!("Invalid macro usage in cond: {}", cond);
+//!         }
+//!         let is_else = match test {
+//!             Some(TokenTree::Token(_, Token::Ident(ident))) if ident.name == "else" => true,
+//!             _ => false,
+//!         };
+//!         conds.push(if is_else || input.peek().is_none() {
+//!             quote!({ $rhs })
+//!         } else {
+//!             let test = test.unwrap();
+//!             quote!(if $test { $rhs } else)
+//!         });
+//!     }
+//!
+//!     conds.into_iter().collect()
 //! }
 //! ```
-//!
-
 #![crate_name = "proc_macro_plugin"]
 #![unstable(feature = "rustc_private", issue = "27812")]
 #![feature(plugin_registrar)]
@@ -87,8 +89,8 @@
 extern crate syntax;
 extern crate syntax_pos;
 
-mod qquote;
-use qquote::qquote;
+mod quote;
+use quote::quote;
 
 use rustc_plugin::Registry;
 use syntax::ext::base::SyntaxExtension;
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_syntax_extension(Symbol::intern("qquote"),
-                                  SyntaxExtension::ProcMacro(Box::new(qquote)));
+    reg.register_syntax_extension(Symbol::intern("quote"),
+                                  SyntaxExtension::ProcMacro(Box::new(quote)));
 }
diff --git a/src/libproc_macro_plugin/qquote.rs b/src/libproc_macro_plugin/qquote.rs
deleted file mode 100644 (file)
index 0276587..0000000
+++ /dev/null
@@ -1,216 +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.
-
-//! # Quasiquoter
-//! This file contains the implementation internals of the quasiquoter provided by `qquote!`.
-
-use syntax::ast::Ident;
-use syntax::parse::token::{self, Token, Lit};
-use syntax::symbol::Symbol;
-use syntax::tokenstream::{self, Delimited, TokenTree, TokenStream};
-use syntax_pos::DUMMY_SP;
-
-use std::iter;
-
-pub fn qquote<'cx>(stream: TokenStream) -> TokenStream {
-    stream.quote()
-}
-
-trait Quote {
-    fn quote(&self) -> TokenStream;
-}
-
-macro_rules! quote_tok {
-    (,) => { Token::Comma };
-    (.) => { Token::Dot };
-    (:) => { Token::Colon };
-    (::) => { Token::ModSep };
-    (!) => { Token::Not };
-    (<) => { Token::Lt };
-    (>) => { Token::Gt };
-    (_) => { Token::Underscore };
-    ($i:ident) => { Token::Ident(Ident::from_str(stringify!($i))) };
-}
-
-macro_rules! quote_tree {
-    ((unquote $($t:tt)*)) => { $($t)* };
-    ((quote $($t:tt)*)) => { ($($t)*).quote() };
-    (($($t:tt)*)) => { delimit(token::Paren, quote!($($t)*)) };
-    ([$($t:tt)*]) => { delimit(token::Bracket, quote!($($t)*)) };
-    ({$($t:tt)*}) => { delimit(token::Brace, quote!($($t)*)) };
-    ($t:tt) => { TokenStream::from(TokenTree::Token(DUMMY_SP, quote_tok!($t))) };
-}
-
-fn delimit(delim: token::DelimToken, stream: TokenStream) -> TokenStream {
-    TokenTree::Delimited(DUMMY_SP, Delimited { delim: delim, tts: stream.into() }).into()
-}
-
-macro_rules! quote {
-    () => { TokenStream::empty() };
-    ($($t:tt)*) => { [ $( quote_tree!($t), )* ].iter().cloned().collect::<TokenStream>() };
-}
-
-impl<T: Quote> Quote for Option<T> {
-    fn quote(&self) -> TokenStream {
-        match *self {
-            Some(ref t) => quote!(::std::option::Option::Some((quote t))),
-            None => quote!(::std::option::Option::None),
-        }
-    }
-}
-
-impl Quote for TokenStream {
-    fn quote(&self) -> TokenStream {
-        if self.is_empty() {
-            return quote!(::syntax::tokenstream::TokenStream::empty());
-        }
-
-        struct Quote(iter::Peekable<tokenstream::Cursor>);
-
-        impl Iterator for Quote {
-            type Item = TokenStream;
-
-            fn next(&mut self) -> Option<TokenStream> {
-                let is_unquote = match self.0.peek() {
-                    Some(&TokenTree::Token(_, Token::Ident(ident))) if ident.name == "unquote" => {
-                        self.0.next();
-                        true
-                    }
-                    _ => false,
-                };
-
-                self.0.next().map(|tree| {
-                    let quoted_tree = if is_unquote { tree.into() } else { tree.quote() };
-                    quote!(::syntax::tokenstream::TokenStream::from((unquote quoted_tree)),)
-                })
-            }
-        }
-
-        let quoted = Quote(self.trees().peekable()).collect::<TokenStream>();
-        quote!([(unquote quoted)].iter().cloned().collect::<::syntax::tokenstream::TokenStream>())
-    }
-}
-
-impl Quote for TokenTree {
-    fn quote(&self) -> TokenStream {
-        match *self {
-            TokenTree::Token(_, ref token) => quote! {
-                ::syntax::tokenstream::TokenTree::Token(::syntax::ext::quote::rt::DUMMY_SP,
-                                                        (quote token))
-            },
-            TokenTree::Delimited(_, ref delimited) => quote! {
-                ::syntax::tokenstream::TokenTree::Delimited(::syntax::ext::quote::rt::DUMMY_SP,
-                                                            (quote delimited))
-            },
-        }
-    }
-}
-
-impl Quote for Delimited {
-    fn quote(&self) -> TokenStream {
-        quote!(::syntax::tokenstream::Delimited {
-            delim: (quote self.delim),
-            tts: (quote self.stream()).into(),
-        })
-    }
-}
-
-impl<'a> Quote for &'a str {
-    fn quote(&self) -> TokenStream {
-        TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Str_(Symbol::intern(self)), None))
-            .into()
-    }
-}
-
-impl Quote for Ident {
-    fn quote(&self) -> TokenStream {
-        // FIXME(jseyfried) quote hygiene
-        quote!(::syntax::ast::Ident::from_str((quote &*self.name.as_str())))
-    }
-}
-
-impl Quote for Symbol {
-    fn quote(&self) -> TokenStream {
-        quote!(::syntax::symbol::Symbol::intern((quote &*self.as_str())))
-    }
-}
-
-impl Quote for Token {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*; $($t:tt)*) => {
-                match *self {
-                    $( Token::$i => quote!(::syntax::parse::token::$i), )*
-                    $( $t )*
-                }
-            }
-        }
-
-        gen_match! {
-            Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot,
-            Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, Question,
-            Underscore;
-
-            Token::OpenDelim(delim) => quote!(::syntax::parse::token::OpenDelim((quote delim))),
-            Token::CloseDelim(delim) => quote!(::syntax::parse::token::CloseDelim((quote delim))),
-            Token::BinOp(tok) => quote!(::syntax::parse::token::BinOp((quote tok))),
-            Token::BinOpEq(tok) => quote!(::syntax::parse::token::BinOpEq((quote tok))),
-            Token::Ident(ident) => quote!(::syntax::parse::token::Ident((quote ident))),
-            Token::Lifetime(ident) => quote!(::syntax::parse::token::Lifetime((quote ident))),
-            Token::Literal(lit, sfx) => quote! {
-                ::syntax::parse::token::Literal((quote lit), (quote sfx))
-            },
-            _ => panic!("Unhandled case!"),
-        }
-    }
-}
-
-impl Quote for token::BinOpToken {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*) => {
-                match *self {
-                    $( token::BinOpToken::$i => quote!(::syntax::parse::token::BinOpToken::$i), )*
-                }
-            }
-        }
-
-        gen_match!(Plus, Minus, Star, Slash, Percent, Caret, And, Or, Shl, Shr)
-    }
-}
-
-impl Quote for Lit {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*) => {
-                match *self {
-                    $( Lit::$i(lit) => quote!(::syntax::parse::token::Lit::$i((quote lit))), )*
-                    _ => panic!("Unsupported literal"),
-                }
-            }
-        }
-
-        gen_match!(Byte, Char, Float, Str_, Integer, ByteStr)
-    }
-}
-
-impl Quote for token::DelimToken {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*) => {
-                match *self {
-                    $(token::DelimToken::$i => { quote!(::syntax::parse::token::DelimToken::$i) })*
-                }
-            }
-        }
-
-        gen_match!(Paren, Bracket, Brace, NoDelim)
-    }
-}
diff --git a/src/libproc_macro_plugin/quote.rs b/src/libproc_macro_plugin/quote.rs
new file mode 100644 (file)
index 0000000..ad71584
--- /dev/null
@@ -0,0 +1,220 @@
+// 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.
+
+//! # Quasiquoter
+//! This file contains the implementation internals of the quasiquoter provided by `qquote!`.
+
+use syntax::ast::Ident;
+use syntax::parse::token::{self, Token, Lit};
+use syntax::symbol::Symbol;
+use syntax::tokenstream::{self, Delimited, TokenTree, TokenStream};
+use syntax_pos::DUMMY_SP;
+
+use std::iter;
+
+pub fn quote<'cx>(stream: TokenStream) -> TokenStream {
+    stream.quote()
+}
+
+trait Quote {
+    fn quote(&self) -> TokenStream;
+}
+
+macro_rules! quote_tok {
+    (,) => { Token::Comma };
+    (.) => { Token::Dot };
+    (:) => { Token::Colon };
+    (::) => { Token::ModSep };
+    (!) => { Token::Not };
+    (<) => { Token::Lt };
+    (>) => { Token::Gt };
+    (_) => { Token::Underscore };
+    ($i:ident) => { Token::Ident(Ident::from_str(stringify!($i))) };
+}
+
+macro_rules! quote_tree {
+    ((unquote $($t:tt)*)) => { $($t)* };
+    ((quote $($t:tt)*)) => { ($($t)*).quote() };
+    (($($t:tt)*)) => { delimit(token::Paren, quote!($($t)*)) };
+    ([$($t:tt)*]) => { delimit(token::Bracket, quote!($($t)*)) };
+    ({$($t:tt)*}) => { delimit(token::Brace, quote!($($t)*)) };
+    ($t:tt) => { TokenStream::from(TokenTree::Token(DUMMY_SP, quote_tok!($t))) };
+}
+
+fn delimit(delim: token::DelimToken, stream: TokenStream) -> TokenStream {
+    TokenTree::Delimited(DUMMY_SP, Delimited { delim: delim, tts: stream.into() }).into()
+}
+
+macro_rules! quote {
+    () => { TokenStream::empty() };
+    ($($t:tt)*) => { [ $( quote_tree!($t), )* ].iter().cloned().collect::<TokenStream>() };
+}
+
+impl<T: Quote> Quote for Option<T> {
+    fn quote(&self) -> TokenStream {
+        match *self {
+            Some(ref t) => quote!(::std::option::Option::Some((quote t))),
+            None => quote!(::std::option::Option::None),
+        }
+    }
+}
+
+impl Quote for TokenStream {
+    fn quote(&self) -> TokenStream {
+        if self.is_empty() {
+            return quote!(::syntax::tokenstream::TokenStream::empty());
+        }
+
+        struct Quoter(iter::Peekable<tokenstream::Cursor>);
+
+        impl Iterator for Quoter {
+            type Item = TokenStream;
+
+            fn next(&mut self) -> Option<TokenStream> {
+                let quoted_tree = if let Some(&TokenTree::Token(_, Token::Dollar)) = self.0.peek() {
+                    self.0.next();
+                    match self.0.next() {
+                        Some(tree @ TokenTree::Token(_, Token::Ident(..))) => Some(tree.into()),
+                        Some(tree @ TokenTree::Token(_, Token::Dollar)) => Some(tree.quote()),
+                        // FIXME(jseyfried): improve these diagnostics
+                        Some(..) => panic!("`$` must be followed by an ident or `$` in `quote!`"),
+                        None => panic!("unexpected trailing `$` in `quote!`"),
+                    }
+                } else {
+                    self.0.next().as_ref().map(Quote::quote)
+                };
+
+                quoted_tree.map(|quoted_tree| {
+                    quote!(::syntax::tokenstream::TokenStream::from((unquote quoted_tree)),)
+                })
+            }
+        }
+
+        let quoted = Quoter(self.trees().peekable()).collect::<TokenStream>();
+        quote!([(unquote quoted)].iter().cloned().collect::<::syntax::tokenstream::TokenStream>())
+    }
+}
+
+impl Quote for TokenTree {
+    fn quote(&self) -> TokenStream {
+        match *self {
+            TokenTree::Token(_, ref token) => quote! {
+                ::syntax::tokenstream::TokenTree::Token(::syntax::ext::quote::rt::DUMMY_SP,
+                                                        (quote token))
+            },
+            TokenTree::Delimited(_, ref delimited) => quote! {
+                ::syntax::tokenstream::TokenTree::Delimited(::syntax::ext::quote::rt::DUMMY_SP,
+                                                            (quote delimited))
+            },
+        }
+    }
+}
+
+impl Quote for Delimited {
+    fn quote(&self) -> TokenStream {
+        quote!(::syntax::tokenstream::Delimited {
+            delim: (quote self.delim),
+            tts: (quote self.stream()).into(),
+        })
+    }
+}
+
+impl<'a> Quote for &'a str {
+    fn quote(&self) -> TokenStream {
+        TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Str_(Symbol::intern(self)), None))
+            .into()
+    }
+}
+
+impl Quote for Ident {
+    fn quote(&self) -> TokenStream {
+        // FIXME(jseyfried) quote hygiene
+        quote!(::syntax::ast::Ident::from_str((quote &*self.name.as_str())))
+    }
+}
+
+impl Quote for Symbol {
+    fn quote(&self) -> TokenStream {
+        quote!(::syntax::symbol::Symbol::intern((quote &*self.as_str())))
+    }
+}
+
+impl Quote for Token {
+    fn quote(&self) -> TokenStream {
+        macro_rules! gen_match {
+            ($($i:ident),*; $($t:tt)*) => {
+                match *self {
+                    $( Token::$i => quote!(::syntax::parse::token::$i), )*
+                    $( $t )*
+                }
+            }
+        }
+
+        gen_match! {
+            Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot,
+            Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, Question,
+            Underscore;
+
+            Token::OpenDelim(delim) => quote!(::syntax::parse::token::OpenDelim((quote delim))),
+            Token::CloseDelim(delim) => quote!(::syntax::parse::token::CloseDelim((quote delim))),
+            Token::BinOp(tok) => quote!(::syntax::parse::token::BinOp((quote tok))),
+            Token::BinOpEq(tok) => quote!(::syntax::parse::token::BinOpEq((quote tok))),
+            Token::Ident(ident) => quote!(::syntax::parse::token::Ident((quote ident))),
+            Token::Lifetime(ident) => quote!(::syntax::parse::token::Lifetime((quote ident))),
+            Token::Literal(lit, sfx) => quote! {
+                ::syntax::parse::token::Literal((quote lit), (quote sfx))
+            },
+            _ => panic!("Unhandled case!"),
+        }
+    }
+}
+
+impl Quote for token::BinOpToken {
+    fn quote(&self) -> TokenStream {
+        macro_rules! gen_match {
+            ($($i:ident),*) => {
+                match *self {
+                    $( token::BinOpToken::$i => quote!(::syntax::parse::token::BinOpToken::$i), )*
+                }
+            }
+        }
+
+        gen_match!(Plus, Minus, Star, Slash, Percent, Caret, And, Or, Shl, Shr)
+    }
+}
+
+impl Quote for Lit {
+    fn quote(&self) -> TokenStream {
+        macro_rules! gen_match {
+            ($($i:ident),*) => {
+                match *self {
+                    $( Lit::$i(lit) => quote!(::syntax::parse::token::Lit::$i((quote lit))), )*
+                    _ => panic!("Unsupported literal"),
+                }
+            }
+        }
+
+        gen_match!(Byte, Char, Float, Str_, Integer, ByteStr)
+    }
+}
+
+impl Quote for token::DelimToken {
+    fn quote(&self) -> TokenStream {
+        macro_rules! gen_match {
+            ($($i:ident),*) => {
+                match *self {
+                    $(token::DelimToken::$i => { quote!(::syntax::parse::token::DelimToken::$i) })*
+                }
+            }
+        }
+
+        gen_match!(Paren, Bracket, Brace, NoDelim)
+    }
+}
index 7a70eda955b69dec324b78be14b67ddf8181d592..189a7344c313058432770a3ce7175470a0fcfc3e 100644 (file)
@@ -22,13 +22,20 @@ struct CFGBuilder<'a, 'tcx: 'a> {
     graph: CFGGraph,
     fn_exit: CFGIndex,
     loop_scopes: Vec<LoopScope>,
+    breakable_block_scopes: Vec<BlockScope>,
+}
+
+#[derive(Copy, Clone)]
+struct BlockScope {
+    block_expr_id: ast::NodeId, // id of breakable block expr node
+    break_index: CFGIndex, // where to go on `break`
 }
 
 #[derive(Copy, Clone)]
 struct LoopScope {
     loop_id: ast::NodeId,     // id of loop/while node
     continue_index: CFGIndex, // where to go on a `loop`
-    break_index: CFGIndex,    // where to go on a `break
+    break_index: CFGIndex,    // where to go on a `break`
 }
 
 pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -53,6 +60,7 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         graph: graph,
         fn_exit: fn_exit,
         loop_scopes: Vec::new(),
+        breakable_block_scopes: Vec::new(),
     };
     body_exit = cfg_builder.expr(&body.value, entry);
     cfg_builder.add_contained_edge(body_exit, fn_exit);
@@ -66,14 +74,34 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     fn block(&mut self, blk: &hir::Block, pred: CFGIndex) -> CFGIndex {
-        let mut stmts_exit = pred;
-        for stmt in &blk.stmts {
-            stmts_exit = self.stmt(stmt, stmts_exit);
-        }
+        if let Some(break_to_expr_id) = blk.break_to_expr_id {
+            let expr_exit = self.add_ast_node(blk.id, &[]);
+
+            self.breakable_block_scopes.push(BlockScope {
+                block_expr_id: break_to_expr_id,
+                break_index: expr_exit,
+            });
+
+            let mut stmts_exit = pred;
+            for stmt in &blk.stmts {
+                stmts_exit = self.stmt(stmt, stmts_exit);
+            }
+            let blk_expr_exit = self.opt_expr(&blk.expr, stmts_exit);
+            self.add_contained_edge(blk_expr_exit, expr_exit);
+
+            self.breakable_block_scopes.pop();
+
+            expr_exit
+        } else {
+            let mut stmts_exit = pred;
+            for stmt in &blk.stmts {
+                stmts_exit = self.stmt(stmt, stmts_exit);
+            }
 
-        let expr_exit = self.opt_expr(&blk.expr, stmts_exit);
+            let expr_exit = self.opt_expr(&blk.expr, stmts_exit);
 
-        self.add_ast_node(blk.id, &[expr_exit])
+            self.add_ast_node(blk.id, &[expr_exit])
+        }
     }
 
     fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex {
@@ -295,18 +323,18 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
 
             hir::ExprBreak(destination, ref opt_expr) => {
                 let v = self.opt_expr(opt_expr, pred);
-                let loop_scope = self.find_scope(expr, destination);
+                let (scope_id, break_dest) =
+                    self.find_scope_edge(expr, destination, ScopeCfKind::Break);
                 let b = self.add_ast_node(expr.id, &[v]);
-                self.add_exiting_edge(expr, b,
-                                      loop_scope, loop_scope.break_index);
+                self.add_exiting_edge(expr, b, scope_id, break_dest);
                 self.add_unreachable_node()
             }
 
             hir::ExprAgain(destination) => {
-                let loop_scope = self.find_scope(expr, destination);
+                let (scope_id, cont_dest) =
+                    self.find_scope_edge(expr, destination, ScopeCfKind::Continue);
                 let a = self.add_ast_node(expr.id, &[pred]);
-                self.add_exiting_edge(expr, a,
-                                      loop_scope, loop_scope.continue_index);
+                self.add_exiting_edge(expr, a, scope_id, cont_dest);
                 self.add_unreachable_node()
             }
 
@@ -552,11 +580,11 @@ fn add_contained_edge(&mut self,
     fn add_exiting_edge(&mut self,
                         from_expr: &hir::Expr,
                         from_index: CFGIndex,
-                        to_loop: LoopScope,
+                        scope_id: ast::NodeId,
                         to_index: CFGIndex) {
         let mut data = CFGEdgeData { exiting_scopes: vec![] };
         let mut scope = self.tcx.region_maps.node_extent(from_expr.id);
-        let target_scope = self.tcx.region_maps.node_extent(to_loop.loop_id);
+        let target_scope = self.tcx.region_maps.node_extent(scope_id);
         while scope != target_scope {
             data.exiting_scopes.push(scope.node_id(&self.tcx.region_maps));
             scope = self.tcx.region_maps.encl_scope(scope);
@@ -576,20 +604,42 @@ fn add_returning_edge(&mut self,
         self.graph.add_edge(from_index, self.fn_exit, data);
     }
 
-    fn find_scope(&self,
+    fn find_scope_edge(&self,
                   expr: &hir::Expr,
-                  destination: hir::Destination) -> LoopScope {
-
-        match destination.loop_id.into() {
-            Ok(loop_id) => {
+                  destination: hir::Destination,
+                  scope_cf_kind: ScopeCfKind) -> (ast::NodeId, CFGIndex) {
+
+        match destination.target_id {
+            hir::ScopeTarget::Block(block_expr_id) => {
+                for b in &self.breakable_block_scopes {
+                    if b.block_expr_id == block_expr_id {
+                        return (block_expr_id, match scope_cf_kind {
+                            ScopeCfKind::Break => b.break_index,
+                            ScopeCfKind::Continue => bug!("can't continue to block"),
+                        });
+                    }
+                }
+                span_bug!(expr.span, "no block expr for id {}", block_expr_id);
+            }
+            hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => {
                 for l in &self.loop_scopes {
                     if l.loop_id == loop_id {
-                        return *l;
+                        return (loop_id, match scope_cf_kind {
+                            ScopeCfKind::Break => l.break_index,
+                            ScopeCfKind::Continue => l.continue_index,
+                        });
                     }
                 }
                 span_bug!(expr.span, "no loop scope for id {}", loop_id);
             }
-            Err(err) => span_bug!(expr.span, "loop scope error: {}", err),
+            hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
+                span_bug!(expr.span, "loop scope error: {}",  err),
         }
     }
 }
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+enum ScopeCfKind {
+    Break,
+    Continue,
+}
index 254cae61152b90f4b20d74ac2f7d566c1f80ec9c..399af258e925167767be1ea6f3417141bfee6ae4 100644 (file)
@@ -89,6 +89,7 @@ pub enum DepNode<D: Clone + Debug> {
     // things read/modify that MIR.
     MirKrate,
     Mir(D),
+    MirShim(Vec<D>),
 
     BorrowCheckKrate,
     BorrowCheck(D),
@@ -258,6 +259,10 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck),
             MatchCheck(ref d) => op(d).map(MatchCheck),
             Mir(ref d) => op(d).map(Mir),
+            MirShim(ref def_ids) => {
+                let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
+                def_ids.map(MirShim)
+            }
             BorrowCheck(ref d) => op(d).map(BorrowCheck),
             RvalueCheck(ref d) => op(d).map(RvalueCheck),
             StabilityCheck(ref d) => op(d).map(StabilityCheck),
index fd6796ccc0bf2b0cd6b7957281a960c99322ff4c..f59b8b757f5cc4de61cb1aae6731a8ee023655e9 100644 (file)
@@ -1008,18 +1008,24 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         }
         ExprBreak(label, ref opt_expr) => {
             label.ident.map(|ident| {
-                if let Ok(loop_id) = label.loop_id.into() {
-                    visitor.visit_def_mention(Def::Label(loop_id));
-                }
+                match label.target_id {
+                    ScopeTarget::Block(node_id) |
+                    ScopeTarget::Loop(LoopIdResult::Ok(node_id)) =>
+                        visitor.visit_def_mention(Def::Label(node_id)),
+                    ScopeTarget::Loop(LoopIdResult::Err(_)) => {},
+                };
                 visitor.visit_name(ident.span, ident.node.name);
             });
             walk_list!(visitor, visit_expr, opt_expr);
         }
         ExprAgain(label) => {
             label.ident.map(|ident| {
-                if let Ok(loop_id) = label.loop_id.into() {
-                    visitor.visit_def_mention(Def::Label(loop_id));
-                }
+                match label.target_id {
+                    ScopeTarget::Block(_) => bug!("can't `continue` to a non-loop block"),
+                    ScopeTarget::Loop(LoopIdResult::Ok(node_id)) =>
+                        visitor.visit_def_mention(Def::Label(node_id)),
+                    ScopeTarget::Loop(LoopIdResult::Err(_)) => {},
+                };
                 visitor.visit_name(ident.span, ident.node.name);
             });
         }
index d966f4899e50fc9c0556d1dd93f7751fc97644d1..81591a5650f07995d948ea2934de04dc460489f0 100644 (file)
@@ -356,22 +356,26 @@ fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned
         o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
     }
 
-    fn lower_destination(&mut self, destination: Option<(NodeId, Spanned<Ident>)>)
+    fn lower_loop_destination(&mut self, destination: Option<(NodeId, Spanned<Ident>)>)
         -> hir::Destination
     {
         match destination {
-            Some((id, label_ident)) => hir::Destination {
-                ident: Some(label_ident),
-                loop_id: if let Def::Label(loop_id) = self.expect_full_def(id) {
+            Some((id, label_ident)) => {
+                let target = if let Def::Label(loop_id) = self.expect_full_def(id) {
                     hir::LoopIdResult::Ok(loop_id)
                 } else {
                     hir::LoopIdResult::Err(hir::LoopIdError::UnresolvedLabel)
+                };
+                hir::Destination {
+                    ident: Some(label_ident),
+                    target_id: hir::ScopeTarget::Loop(target),
                 }
             },
             None => hir::Destination {
                 ident: None,
-                loop_id: self.loop_scopes.last().map(|innermost_loop_id| Ok(*innermost_loop_id))
-                            .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)).into()
+                target_id: hir::ScopeTarget::Loop(
+                    self.loop_scopes.last().map(|innermost_loop_id| Ok(*innermost_loop_id))
+                            .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)).into())
             }
         }
     }
@@ -990,7 +994,7 @@ fn lower_bounds(&mut self, bounds: &[TyParamBound]) -> hir::TyParamBounds {
         bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
     }
 
-    fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
+    fn lower_block(&mut self, b: &Block, break_to: Option<NodeId>) -> P<hir::Block> {
         let mut expr = None;
 
         let mut stmts = b.stmts.iter().flat_map(|s| self.lower_stmt(s)).collect::<Vec<_>>();
@@ -1008,6 +1012,7 @@ fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
             expr: expr,
             rules: self.lower_block_check_mode(&b.rules),
             span: b.span,
+            break_to_expr_id: break_to,
         })
     }
 
@@ -1085,7 +1090,7 @@ fn lower_item_kind(&mut self,
             }
             ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
                 self.with_new_scopes(|this| {
-                    let body = this.lower_block(body);
+                    let body = this.lower_block(body, None);
                     let body = this.expr_block(body, ThinVec::new());
                     let body_id = this.record_body(body, Some(decl));
                     hir::ItemFn(this.lower_fn_decl(decl),
@@ -1179,7 +1184,7 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                                                    hir::TraitMethod::Required(names))
                     }
                     TraitItemKind::Method(ref sig, Some(ref body)) => {
-                        let body = this.lower_block(body);
+                        let body = this.lower_block(body, None);
                         let expr = this.expr_block(body, ThinVec::new());
                         let body_id = this.record_body(expr, Some(&sig.decl));
                         hir::TraitItemKind::Method(this.lower_method_sig(sig),
@@ -1235,7 +1240,7 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
                         hir::ImplItemKind::Const(this.lower_ty(ty), body_id)
                     }
                     ImplItemKind::Method(ref sig, ref body) => {
-                        let body = this.lower_block(body);
+                        let body = this.lower_block(body, None);
                         let expr = this.expr_block(body, ThinVec::new());
                         let body_id = this.record_body(expr, Some(&sig.decl));
                         hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id)
@@ -1662,6 +1667,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                                     id: id,
                                     rules: hir::DefaultBlock,
                                     span: span,
+                                    break_to_expr_id: None,
                                 });
                                 P(self.expr_block(blk, ThinVec::new()))
                             }
@@ -1669,24 +1675,24 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                         }
                     });
 
-                    hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk), else_opt)
+                    hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk, None), else_opt)
                 }
                 ExprKind::While(ref cond, ref body, opt_ident) => {
                     self.with_loop_scope(e.id, |this|
                         hir::ExprWhile(
                             this.with_loop_condition_scope(|this| P(this.lower_expr(cond))),
-                            this.lower_block(body),
+                            this.lower_block(body, None),
                             this.lower_opt_sp_ident(opt_ident)))
                 }
                 ExprKind::Loop(ref body, opt_ident) => {
                     self.with_loop_scope(e.id, |this|
-                        hir::ExprLoop(this.lower_block(body),
+                        hir::ExprLoop(this.lower_block(body, None),
                                       this.lower_opt_sp_ident(opt_ident),
                                       hir::LoopSource::Loop))
                 }
                 ExprKind::Catch(ref body) => {
-                    // FIXME(cramertj): Add catch to HIR
-                    self.with_catch_scope(e.id, |this| hir::ExprBlock(this.lower_block(body)))
+                    self.with_catch_scope(e.id, |this|
+                        hir::ExprBlock(this.lower_block(body, Some(e.id))))
                 }
                 ExprKind::Match(ref expr, ref arms) => {
                     hir::ExprMatch(P(self.lower_expr(expr)),
@@ -1704,7 +1710,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                         })
                     })
                 }
-                ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk)),
+                ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk, None)),
                 ExprKind::Assign(ref el, ref er) => {
                     hir::ExprAssign(P(self.lower_expr(el)), P(self.lower_expr(er)))
                 }
@@ -1783,10 +1789,11 @@ fn make_struct(this: &mut LoweringContext,
                     let label_result = if self.is_in_loop_condition && opt_ident.is_none() {
                         hir::Destination {
                             ident: opt_ident,
-                            loop_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
+                            target_id: hir::ScopeTarget::Loop(
+                                Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into()),
                         }
                     } else {
-                        self.lower_destination(opt_ident.map(|ident| (e.id, ident)))
+                        self.lower_loop_destination(opt_ident.map(|ident| (e.id, ident)))
                     };
                     hir::ExprBreak(
                             label_result,
@@ -1797,11 +1804,11 @@ fn make_struct(this: &mut LoweringContext,
                         if self.is_in_loop_condition && opt_ident.is_none() {
                             hir::Destination {
                                 ident: opt_ident,
-                                loop_id: Err(
-                                    hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
+                                target_id: hir::ScopeTarget::Loop(Err(
+                                    hir::LoopIdError::UnlabeledCfInWhileCondition).into()),
                             }
                         } else {
-                            self.lower_destination(opt_ident.map( |ident| (e.id, ident)))
+                            self.lower_loop_destination(opt_ident.map( |ident| (e.id, ident)))
                         }),
                 ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
                 ExprKind::InlineAsm(ref asm) => {
@@ -1859,7 +1866,7 @@ fn make_struct(this: &mut LoweringContext,
 
                     // `<pat> => <body>`
                     let pat_arm = {
-                        let body = self.lower_block(body);
+                        let body = self.lower_block(body, None);
                         let body_expr = P(self.expr_block(body, ThinVec::new()));
                         let pat = self.lower_pat(pat);
                         self.arm(hir_vec![pat], body_expr)
@@ -1946,7 +1953,7 @@ fn make_struct(this: &mut LoweringContext,
                     // Note that the block AND the condition are evaluated in the loop scope.
                     // This is done to allow `break` from inside the condition of the loop.
                     let (body, break_expr, sub_expr) = self.with_loop_scope(e.id, |this| (
-                        this.lower_block(body),
+                        this.lower_block(body, None),
                         this.expr_break(e.span, ThinVec::new()),
                         this.with_loop_condition_scope(|this| P(this.lower_expr(sub_expr))),
                     ));
@@ -2007,7 +2014,8 @@ fn make_struct(this: &mut LoweringContext,
 
                     // `::std::option::Option::Some(<pat>) => <body>`
                     let pat_arm = {
-                        let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body));
+                        let body_block = self.with_loop_scope(e.id,
+                                                              |this| this.lower_block(body, None));
                         let body_expr = P(self.expr_block(body_block, ThinVec::new()));
                         let pat = self.lower_pat(pat);
                         let some_pat = self.pat_some(e.span, pat);
@@ -2090,14 +2098,12 @@ fn make_struct(this: &mut LoweringContext,
                     // match Carrier::translate(<expr>) {
                     //     Ok(val) => #[allow(unreachable_code)] val,
                     //     Err(err) => #[allow(unreachable_code)]
+                    //                 // If there is an enclosing `catch {...}`
+                    //                 break 'catch_target Carrier::from_error(From::from(err)),
+                    //                 // Otherwise
                     //                 return Carrier::from_error(From::from(err)),
                     // }
 
-                    // FIXME(cramertj): implement breaking to catch
-                    if !self.catch_scopes.is_empty() {
-                        bug!("`?` in catch scopes is unimplemented")
-                    }
-
                     let unstable_span = self.allow_internal_unstable("?", e.span);
 
                     // Carrier::translate(<expr>)
@@ -2157,9 +2163,24 @@ fn make_struct(this: &mut LoweringContext,
                             P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
                         };
 
-                        let ret_expr = P(self.expr(e.span,
-                                                   hir::Expr_::ExprRet(Some(from_err_expr)),
-                                                                       ThinVec::from(attrs)));
+                        let thin_attrs = ThinVec::from(attrs);
+                        let catch_scope = self.catch_scopes.last().map(|x| *x);
+                        let ret_expr = if let Some(catch_node) = catch_scope {
+                            P(self.expr(
+                                e.span,
+                                hir::ExprBreak(
+                                    hir::Destination {
+                                        ident: None,
+                                        target_id: hir::ScopeTarget::Block(catch_node),
+                                    },
+                                    Some(from_err_expr)
+                                ),
+                                thin_attrs))
+                        } else {
+                            P(self.expr(e.span,
+                                        hir::Expr_::ExprRet(Some(from_err_expr)),
+                                        thin_attrs))
+                        };
 
                         let err_pat = self.pat_err(e.span, err_local);
                         self.arm(hir_vec![err_pat], ret_expr)
@@ -2302,7 +2323,7 @@ fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
     }
 
     fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
-        let expr_break = hir::ExprBreak(self.lower_destination(None), None);
+        let expr_break = hir::ExprBreak(self.lower_loop_destination(None), None);
         P(self.expr(span, expr_break, attrs))
     }
 
@@ -2415,6 +2436,7 @@ fn block_all(&mut self, span: Span, stmts: hir::HirVec<hir::Stmt>, expr: Option<
             id: self.next_id(),
             rules: hir::DefaultBlock,
             span: span,
+            break_to_expr_id: None,
         }
     }
 
@@ -2519,6 +2541,7 @@ fn signal_block_expr(&mut self,
             id: id,
             stmts: stmts,
             expr: Some(expr),
+            break_to_expr_id: None,
         });
         self.expr_block(block, attrs)
     }
index 22bc28eb3fec0a00e90a08bdb4fc7af268c5fa1a..edcfcffaa03a4ddb44ac7cba5841cf1ec646ecf0 100644 (file)
@@ -485,6 +485,9 @@ pub struct Block {
     /// Distinguishes between `unsafe { ... }` and `{ ... }`
     pub rules: BlockCheckMode,
     pub span: Span,
+    /// The id of the expression that `break` breaks to if the block can be broken out of.
+    /// Currently only `Some(_)` for `catch {}` blocks
+    pub break_to_expr_id: Option<NodeId>,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
@@ -1080,6 +1083,22 @@ fn from(res: Result<NodeId, LoopIdError>) -> Self {
     }
 }
 
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum ScopeTarget {
+    Block(NodeId),
+    Loop(LoopIdResult),
+}
+
+impl ScopeTarget {
+    pub fn opt_id(self) -> Option<NodeId> {
+        match self {
+            ScopeTarget::Block(node_id) |
+            ScopeTarget::Loop(LoopIdResult::Ok(node_id)) => Some(node_id),
+            ScopeTarget::Loop(LoopIdResult::Err(_)) => None,
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub struct Destination {
     // This is `Some(_)` iff there is an explicit user-specified `label
@@ -1087,7 +1106,7 @@ pub struct Destination {
 
     // These errors are caught and then reported during the diagnostics pass in
     // librustc_passes/loops.rs
-    pub loop_id: LoopIdResult,
+    pub target_id: ScopeTarget,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -1468,6 +1487,18 @@ pub enum Visibility {
     Inherited,
 }
 
+impl Visibility {
+    pub fn is_pub_restricted(&self) -> bool {
+        use self::Visibility::*;
+        match self {
+            &Public |
+            &Inherited => false,
+            &Crate |
+            &Restricted { .. } => true,
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct StructField {
     pub span: Span,
index c4fccdcb9eb6220ce01c6727797aa487ca098e88..a007c9d2c43a93592e587b45160788e650b7c4a5 100644 (file)
@@ -34,7 +34,7 @@
 #![feature(libc)]
 #![feature(loop_break_value)]
 #![feature(nonzero)]
-#![feature(pub_restricted)]
+#![cfg_attr(stage0, feature(pub_restricted))]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
index b9f1611f62bafd2344a8291bd02c820949f0de51..81a415a2f530964427287920165122471f528701 100644 (file)
@@ -335,7 +335,7 @@ pub fn collect_language_items(session: &Session,
 
     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
     BoxFreeFnLangItem,               "box_free",                box_free_fn;
-    StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;
+    DropInPlaceFnLangItem,             "drop_in_place",           drop_in_place_fn;
 
     StartFnLangItem,                 "start",                   start_fn;
 
@@ -355,8 +355,6 @@ pub fn collect_language_items(session: &Session,
     ContravariantLifetimeItem,       "contravariant_lifetime",  contravariant_lifetime;
     InvariantLifetimeItem,           "invariant_lifetime",      invariant_lifetime;
 
-    NoCopyItem,                      "no_copy_bound",           no_copy_bound;
-
     NonZeroItem,                     "non_zero",                non_zero;
 
     DebugTraitLangItem,              "debug_trait",             debug_trait;
index a8c1559ae2373b309ca0072d0c0ec90790d1f917..769dc8aeb54ddce49744a685505a047dd6da0e41 100644 (file)
@@ -516,14 +516,15 @@ struct Liveness<'a, 'tcx: 'a> {
     s: Specials,
     successors: Vec<LiveNode>,
     users: Vec<Users>,
-    // The list of node IDs for the nested loop scopes
-    // we're in.
-    loop_scope: Vec<NodeId>,
+
     // mappings from loop node ID to LiveNode
     // ("break" label should map to loop node ID,
     // it probably doesn't now)
     break_ln: NodeMap<LiveNode>,
-    cont_ln: NodeMap<LiveNode>
+    cont_ln: NodeMap<LiveNode>,
+
+    // mappings from node ID to LiveNode for "breakable" blocks-- currently only `catch {...}`
+    breakable_block_ln: NodeMap<LiveNode>,
 }
 
 impl<'a, 'tcx> Liveness<'a, 'tcx> {
@@ -550,9 +551,9 @@ fn new(ir: &'a mut IrMaps<'a, 'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
             s: specials,
             successors: vec![invalid_node(); num_live_nodes],
             users: vec![invalid_users(); num_live_nodes * num_vars],
-            loop_scope: Vec::new(),
             break_ln: NodeMap(),
             cont_ln: NodeMap(),
+            breakable_block_ln: NodeMap(),
         }
     }
 
@@ -793,15 +794,17 @@ fn compute(&mut self, body: &hir::Expr) -> LiveNode {
         debug!("compute: using id for body, {}", self.ir.tcx.hir.node_to_pretty_string(body.id));
 
         let exit_ln = self.s.exit_ln;
-        let entry_ln: LiveNode = self.with_loop_nodes(body.id, exit_ln, exit_ln, |this| {
-            // the fallthrough exit is only for those cases where we do not
-            // explicitly return:
-            let s = this.s;
-            this.init_from_succ(s.fallthrough_ln, s.exit_ln);
-            this.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ);
-
-            this.propagate_through_expr(body, s.fallthrough_ln)
-        });
+
+        self.break_ln.insert(body.id, exit_ln);
+        self.cont_ln.insert(body.id, exit_ln);
+
+        // the fallthrough exit is only for those cases where we do not
+        // explicitly return:
+        let s = self.s;
+        self.init_from_succ(s.fallthrough_ln, s.exit_ln);
+        self.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ);
+
+        let entry_ln = self.propagate_through_expr(body, s.fallthrough_ln);
 
         // hack to skip the loop unless debug! is enabled:
         debug!("^^ liveness computation results for body {} (entry={:?})",
@@ -818,6 +821,9 @@ fn compute(&mut self, body: &hir::Expr) -> LiveNode {
 
     fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode)
                                -> LiveNode {
+        if let Some(break_to_expr_id) = blk.break_to_expr_id {
+            self.breakable_block_ln.insert(break_to_expr_id, succ);
+        }
         let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ);
         blk.stmts.iter().rev().fold(succ, |succ, stmt| {
             self.propagate_through_stmt(stmt, succ)
@@ -901,30 +907,32 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
           }
 
           hir::ExprClosure(.., blk_id, _) => {
-              debug!("{} is an ExprClosure",
-                     self.ir.tcx.hir.node_to_pretty_string(expr.id));
+              debug!("{} is an ExprClosure", self.ir.tcx.hir.node_to_pretty_string(expr.id));
 
               /*
               The next-node for a break is the successor of the entire
               loop. The next-node for a continue is the top of this loop.
               */
               let node = self.live_node(expr.id, expr.span);
-              self.with_loop_nodes(blk_id.node_id, succ, node, |this| {
-
-                 // the construction of a closure itself is not important,
-                 // but we have to consider the closed over variables.
-                 let caps = match this.ir.capture_info_map.get(&expr.id) {
-                    Some(caps) => caps.clone(),
-                    None => {
-                        span_bug!(expr.span, "no registered caps");
-                     }
-                 };
-                 caps.iter().rev().fold(succ, |succ, cap| {
-                     this.init_from_succ(cap.ln, succ);
-                     let var = this.variable(cap.var_nid, expr.span);
-                     this.acc(cap.ln, var, ACC_READ | ACC_USE);
-                     cap.ln
-                 })
+
+              let break_ln = succ;
+              let cont_ln = node;
+              self.break_ln.insert(blk_id.node_id, break_ln);
+              self.cont_ln.insert(blk_id.node_id, cont_ln);
+
+              // the construction of a closure itself is not important,
+              // but we have to consider the closed over variables.
+              let caps = match self.ir.capture_info_map.get(&expr.id) {
+                  Some(caps) => caps.clone(),
+                  None => {
+                      span_bug!(expr.span, "no registered caps");
+                  }
+              };
+              caps.iter().rev().fold(succ, |succ, cap| {
+                  self.init_from_succ(cap.ln, succ);
+                  let var = self.variable(cap.var_nid, expr.span);
+                  self.acc(cap.ln, var, ACC_READ | ACC_USE);
+                  cap.ln
               })
           }
 
@@ -1003,28 +1011,33 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
 
           hir::ExprBreak(label, ref opt_expr) => {
               // Find which label this break jumps to
-              let sc = match label.loop_id.into() {
-                  Ok(loop_id) => loop_id,
-                  Err(err) => span_bug!(expr.span, "loop scope error: {}", err),
-              };
+              let target = match label.target_id {
+                    hir::ScopeTarget::Block(node_id) =>
+                        self.breakable_block_ln.get(&node_id),
+                    hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(node_id)) =>
+                        self.break_ln.get(&node_id),
+                    hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
+                        span_bug!(expr.span, "loop scope error: {}", err),
+              }.map(|x| *x);
 
               // Now that we know the label we're going to,
               // look it up in the break loop nodes table
 
-              match self.break_ln.get(&sc) {
-                  Some(&b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b),
+              match target {
+                  Some(b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b),
                   None => span_bug!(expr.span, "break to unknown label")
               }
           }
 
           hir::ExprAgain(label) => {
               // Find which label this expr continues to
-              let sc = match label.loop_id.into() {
-                  Ok(loop_id) => loop_id,
-                  Err(err) => span_bug!(expr.span, "loop scope error: {}", err),
+              let sc = match label.target_id {
+                    hir::ScopeTarget::Block(_) => bug!("can't `continue` to a non-loop block"),
+                    hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(node_id)) => node_id,
+                    hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
+                        span_bug!(expr.span, "loop scope error: {}", err),
               };
 
-
               // Now that we know the label we're going to,
               // look it up in the continue loop nodes table
 
@@ -1287,14 +1300,16 @@ fn propagate_through_loop(&mut self,
         debug!("propagate_through_loop: using id for loop body {} {}",
                expr.id, self.ir.tcx.hir.node_to_pretty_string(body.id));
 
-        let (cond_ln, body_ln) = self.with_loop_nodes(expr.id, succ, ln, |this| {
-            let cond_ln = match kind {
-                LoopLoop => ln,
-                WhileLoop(ref cond) => this.propagate_through_expr(&cond, ln),
-            };
-            let body_ln = this.propagate_through_block(body, cond_ln);
-            (cond_ln, body_ln)
-        });
+        let break_ln = succ;
+        let cont_ln = ln;
+        self.break_ln.insert(expr.id, break_ln);
+        self.cont_ln.insert(expr.id, cont_ln);
+
+        let cond_ln = match kind {
+            LoopLoop => ln,
+            WhileLoop(ref cond) => self.propagate_through_expr(&cond, ln),
+        };
+        let body_ln = self.propagate_through_block(body, cond_ln);
 
         // repeat until fixed point is reached:
         while self.merge_from_succ(ln, body_ln, first_merge) {
@@ -1307,29 +1322,11 @@ fn propagate_through_loop(&mut self,
                 }
             };
             assert!(cond_ln == new_cond_ln);
-            assert!(body_ln == self.with_loop_nodes(expr.id, succ, ln,
-            |this| this.propagate_through_block(body, cond_ln)));
+            assert!(body_ln == self.propagate_through_block(body, cond_ln));
         }
 
         cond_ln
     }
-
-    fn with_loop_nodes<R, F>(&mut self,
-                             loop_node_id: NodeId,
-                             break_ln: LiveNode,
-                             cont_ln: LiveNode,
-                             f: F)
-                             -> R where
-        F: FnOnce(&mut Liveness<'a, 'tcx>) -> R,
-    {
-        debug!("with_loop_nodes: {} {}", loop_node_id, break_ln.get());
-        self.loop_scope.push(loop_node_id);
-        self.break_ln.insert(loop_node_id, break_ln);
-        self.cont_ln.insert(loop_node_id, cont_ln);
-        let r = f(self);
-        self.loop_scope.pop();
-        r
-    }
 }
 
 // _______________________________________________________________________
index fea576f7067807bf2933906496e5e5610b6df142..9fdb86657769917bb49fa6c98830aed10d0d26ca 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_data_structures::control_flow_graph::ControlFlowGraph;
 use hir::def::CtorKind;
 use hir::def_id::DefId;
-use ty::subst::Substs;
+use ty::subst::{Subst, Substs};
 use ty::{self, AdtDef, ClosureSubsts, Region, Ty};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use util::ppaux;
@@ -467,7 +467,7 @@ pub enum TerminatorKind<'tcx> {
         values: Cow<'tcx, [ConstInt]>,
 
         /// Possible branch sites. The last element of this vector is used
-        /// for the otherwise branch, so values.len() == targets.len() + 1
+        /// for the otherwise branch, so targets.len() == values.len() + 1
         /// should hold.
         // This invariant is quite non-obvious and also could be improved.
         // One way to make this invariant is to have something like this instead:
@@ -982,6 +982,22 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
     }
 }
 
+impl<'tcx> Operand<'tcx> {
+    pub fn item<'a>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+                    def_id: DefId,
+                    substs: &'tcx Substs<'tcx>,
+                    span: Span)
+                    -> Self
+    {
+        Operand::Constant(Constant {
+            span: span,
+            ty: tcx.item_type(def_id).subst(tcx, substs),
+            literal: Literal::Item { def_id, substs }
+        })
+    }
+
+}
+
 ///////////////////////////////////////////////////////////////////////////
 /// Rvalues
 
index 7e7d06e4b814e681e025a1b33e5966582c7043c0..c71fc28b4d6b3a71776fae56652048f8d484078b 100644 (file)
@@ -40,7 +40,7 @@
 pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
 pub use self::select::{MethodMatchedData}; // intentionally don't export variants
 pub use self::specialize::{OverlapError, specialization_graph, specializes, translate_substs};
-pub use self::specialize::{SpecializesCache, find_method};
+pub use self::specialize::{SpecializesCache, find_associated_item};
 pub use self::util::elaborate_predicates;
 pub use self::util::supertraits;
 pub use self::util::Supertraits;
index 2c99ee21b0f730b401d91ed4994b34bc111a8816..50a4d982832ace739c8c78b7afac69938d07f6c7 100644 (file)
@@ -29,8 +29,6 @@
 use ty::{self, TyCtxt, TypeFoldable};
 use syntax_pos::DUMMY_SP;
 
-use syntax::ast;
-
 pub mod specialization_graph;
 
 /// Information pertinent to an overlapping impl error.
@@ -106,22 +104,23 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 }
 
 /// Given a selected impl described by `impl_data`, returns the
-/// definition and substitions for the method with the name `name`,
-/// and trait method substitutions `substs`, in that impl, a less
-/// specialized impl, or the trait default, whichever applies.
-pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             name: ast::Name,
-                             substs: &'tcx Substs<'tcx>,
-                             impl_data: &super::VtableImplData<'tcx, ()>)
-                             -> (DefId, &'tcx Substs<'tcx>)
-{
+/// definition and substitions for the method with the name `name`
+/// the kind `kind`, and trait method substitutions `substs`, in
+/// that impl, a less specialized impl, or the trait default,
+/// whichever applies.
+pub fn find_associated_item<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    item: &ty::AssociatedItem,
+    substs: &'tcx Substs<'tcx>,
+    impl_data: &super::VtableImplData<'tcx, ()>,
+) -> (DefId, &'tcx Substs<'tcx>) {
     assert!(!substs.needs_infer());
 
     let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
     let trait_def = tcx.lookup_trait_def(trait_def_id);
 
     let ancestors = trait_def.ancestors(impl_data.impl_def_id);
-    match ancestors.defs(tcx, name, ty::AssociatedKind::Method).next() {
+    match ancestors.defs(tcx, item.name, item.kind).next() {
         Some(node_item) => {
             let substs = tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
                 let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
@@ -137,7 +136,7 @@ pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             (node_item.item.def_id, substs)
         }
         None => {
-            bug!("method {:?} not found in {:?}", name, impl_data.impl_def_id)
+            bug!("{:?} not found in {:?}", item, impl_data.impl_def_id)
         }
     }
 }
index a0aeb4107c156c17dd4c19cea5762942fc517a9d..5543223105b444c37f5d8e512588661627c094a1 100644 (file)
@@ -1469,6 +1469,15 @@ fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> S
     }
 }
 
+impl<'a, T, R> InternIteratorElement<T, R> for &'a T
+    where T: Clone + 'a
+{
+    type Output = R;
+    fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
+        f(&iter.cloned().collect::<AccumulateVec<[_; 8]>>())
+    }
+}
+
 impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
     type Output = Result<R, E>;
     fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
new file mode 100644 (file)
index 0000000..67287f1
--- /dev/null
@@ -0,0 +1,128 @@
+// 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.
+
+use dep_graph::DepNode;
+use hir::def_id::DefId;
+use ty::{self, Ty, TypeFoldable, Substs};
+use util::ppaux;
+
+use std::borrow::Cow;
+use std::fmt;
+use syntax::ast;
+
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub struct Instance<'tcx> {
+    pub def: InstanceDef<'tcx>,
+    pub substs: &'tcx Substs<'tcx>,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum InstanceDef<'tcx> {
+    Item(DefId),
+    Intrinsic(DefId),
+    // <fn() as FnTrait>::call_*
+    // def-id is FnTrait::call_*
+    FnPtrShim(DefId, Ty<'tcx>),
+    // <Trait as Trait>::fn
+    Virtual(DefId, usize),
+    // <[mut closure] as FnOnce>::call_once
+    ClosureOnceShim { call_once: DefId },
+    // drop_in_place::<T>; None for empty drop glue.
+    DropGlue(DefId, Option<Ty<'tcx>>),
+}
+
+impl<'tcx> InstanceDef<'tcx> {
+    #[inline]
+    pub fn def_id(&self) -> DefId {
+        match *self {
+            InstanceDef::Item(def_id) |
+            InstanceDef::FnPtrShim(def_id, _) |
+            InstanceDef::Virtual(def_id, _) |
+            InstanceDef::Intrinsic(def_id, ) |
+            InstanceDef::ClosureOnceShim { call_once: def_id }
+                => def_id,
+            InstanceDef::DropGlue(def_id, _) => def_id
+        }
+    }
+
+    #[inline]
+    pub fn def_ty<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
+        tcx.item_type(self.def_id())
+    }
+
+    #[inline]
+    pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Cow<'tcx, [ast::Attribute]> {
+        tcx.get_attrs(self.def_id())
+    }
+
+    pub(crate) fn dep_node(&self) -> DepNode<DefId> {
+        // HACK: def-id binning, project-style; someone replace this with
+        // real on-demand.
+        let ty = match self {
+            &InstanceDef::FnPtrShim(_, ty) => Some(ty),
+            &InstanceDef::DropGlue(_, ty) => ty,
+            _ => None
+        }.into_iter();
+
+        DepNode::MirShim(
+            Some(self.def_id()).into_iter().chain(
+                ty.flat_map(|t| t.walk()).flat_map(|t| match t.sty {
+                   ty::TyAdt(adt_def, _) => Some(adt_def.did),
+                   ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
+                   _ => None,
+               })
+            ).collect()
+        )
+    }
+}
+
+impl<'tcx> fmt::Display for Instance<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ppaux::parameterized(f, self.substs, self.def_id(), &[])?;
+        match self.def {
+            InstanceDef::Item(_) => Ok(()),
+            InstanceDef::Intrinsic(_) => {
+                write!(f, " - intrinsic")
+            }
+            InstanceDef::Virtual(_, num) => {
+                write!(f, " - shim(#{})", num)
+            }
+            InstanceDef::FnPtrShim(_, ty) => {
+                write!(f, " - shim({:?})", ty)
+            }
+            InstanceDef::ClosureOnceShim { .. } => {
+                write!(f, " - shim")
+            }
+            InstanceDef::DropGlue(_, ty) => {
+                write!(f, " - shim({:?})", ty)
+            }
+        }
+    }
+}
+
+impl<'a, 'b, 'tcx> Instance<'tcx> {
+    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
+               -> Instance<'tcx> {
+        assert!(substs.is_normalized_for_trans() && !substs.has_escaping_regions(),
+                "substs of instance {:?} not normalized for trans: {:?}",
+                def_id, substs);
+        Instance { def: InstanceDef::Item(def_id), substs: substs }
+    }
+
+    pub fn mono(tcx: ty::TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
+        Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
+    }
+
+    #[inline]
+    pub fn def_id(&self) -> DefId {
+        self.def.def_id()
+    }
+}
index af05c0c43113b3e34a6601c6c6e7fdea494ea6eb..ac8c38c7d585664d05d58efd4832d59e7a61e38e 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
-use hir::def_id::{CrateNum, DefId};
+use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use middle::const_val::ConstVal;
 use mir;
 use ty::{self, Ty, TyCtxt};
@@ -24,6 +24,16 @@ trait Key {
     fn default_span(&self, tcx: TyCtxt) -> Span;
 }
 
+impl<'tcx> Key for ty::InstanceDef<'tcx> {
+    fn map_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+
+    fn default_span(&self, tcx: TyCtxt) -> Span {
+        tcx.def_span(self.def_id())
+    }
+}
+
 impl Key for CrateNum {
     fn map_crate(&self) -> CrateNum {
         *self
@@ -83,9 +93,9 @@ fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
     }
 }
 
-pub struct CycleError<'a> {
+pub struct CycleError<'a, 'tcx: 'a> {
     span: Span,
-    cycle: RefMut<'a, [(Span, Query)]>,
+    cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -110,8 +120,8 @@ pub fn report_cycle(self, CycleError { span, cycle }: CycleError) {
         err.emit();
     }
 
-    fn cycle_check<F, R>(self, span: Span, query: Query, compute: F)
-                         -> Result<R, CycleError<'a>>
+    fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F)
+                         -> Result<R, CycleError<'a, 'gcx>>
         where F: FnOnce() -> R
     {
         {
@@ -172,13 +182,20 @@ fn describe(_: TyCtxt, _: CrateNum) -> String {
     }
 }
 
+impl<'tcx> QueryDescription for queries::mir_shims<'tcx> {
+    fn describe(tcx: TyCtxt, def: ty::InstanceDef<'tcx>) -> String {
+        format!("generating MIR shim for `{}`",
+                tcx.item_path_str(def.def_id()))
+    }
+}
+
 macro_rules! define_maps {
     (<$tcx:tt>
      $($(#[$attr:meta])*
        pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => {
         pub struct Maps<$tcx> {
             providers: IndexVec<CrateNum, Providers<$tcx>>,
-            query_stack: RefCell<Vec<(Span, Query)>>,
+            query_stack: RefCell<Vec<(Span, Query<$tcx>)>>,
             $($(#[$attr])* pub $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),*
         }
 
@@ -196,11 +213,11 @@ pub fn new(dep_graph: DepGraph,
 
         #[allow(bad_style)]
         #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-        pub enum Query {
+        pub enum Query<$tcx> {
             $($(#[$attr])* $name($K)),*
         }
 
-        impl Query {
+        impl<$tcx> Query<$tcx> {
             pub fn describe(&self, tcx: TyCtxt) -> String {
                 match *self {
                     $(Query::$name(key) => queries::$name::describe(tcx, key)),*
@@ -233,7 +250,7 @@ fn try_get_with<F, R>(tcx: TyCtxt<'a, $tcx, 'lcx>,
                                   mut span: Span,
                                   key: $K,
                                   f: F)
-                                  -> Result<R, CycleError<'a>>
+                                  -> Result<R, CycleError<'a, $tcx>>
                 where F: FnOnce(&$V) -> R
             {
                 if let Some(result) = tcx.maps.$name.borrow().get(&key) {
@@ -256,7 +273,7 @@ fn try_get_with<F, R>(tcx: TyCtxt<'a, $tcx, 'lcx>,
             }
 
             pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
-                           -> Result<$V, CycleError<'a>> {
+                           -> Result<$V, CycleError<'a, $tcx>> {
                 Self::try_get_with(tcx, span, key, Clone::clone)
             }
 
@@ -387,7 +404,9 @@ fn default() -> Self {
 
     /// Results of evaluating monomorphic constants embedded in
     /// other items, such as enum variant explicit discriminants.
-    pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result<ConstVal<'tcx>, ()>
+    pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result<ConstVal<'tcx>, ()>,
+
+    pub mir_shims: mir_shim(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
 }
 
 fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
@@ -397,3 +416,7 @@ fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
 fn coherent_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
     DepNode::Coherence
 }
+
+fn mir_shim(instance: ty::InstanceDef) -> DepNode<DefId> {
+    instance.dep_node()
+}
index 3c37c7353d683b739e76b4a4358dd911984481ec..c4192ffc697cecefaad97bae83db8aaddf5b5be1 100644 (file)
@@ -73,6 +73,8 @@
 pub use self::context::{TyCtxt, GlobalArenas, tls};
 pub use self::context::{Lift, TypeckTables};
 
+pub use self::instance::{Instance, InstanceDef};
+
 pub use self::trait_def::{TraitDef, TraitFlags};
 
 pub use self::maps::queries;
 mod contents;
 mod context;
 mod flags;
+mod instance;
 mod structural_impls;
 mod sty;
 
@@ -1264,10 +1267,17 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                                                     def_id,
                                                     ROOT_CODE_EXTENT)
             }
-            _ => {
+            Some(hir_map::NodeStructCtor(..)) |
+            Some(hir_map::NodeVariant(..)) => {
+                let def_id = tcx.hir.local_def_id(id);
+                tcx.construct_parameter_environment(tcx.hir.span(id),
+                                                    def_id,
+                                                    ROOT_CODE_EXTENT)
+            }
+            it => {
                 bug!("ParameterEnvironment::from_item(): \
-                      `{}` is not an item",
-                     tcx.hir.node_to_string(id))
+                      `{}` = {:?} is unsupported",
+                     tcx.hir.node_to_string(id), it)
             }
         }
     }
@@ -2302,6 +2312,16 @@ pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> {
         queries::mir::get(self, DUMMY_SP, did).borrow()
     }
 
+    /// Return the possibly-auto-generated MIR of a (DefId, Subst) pair.
+    pub fn instance_mir(self, instance: ty::InstanceDef<'gcx>)
+                        -> Ref<'gcx, Mir<'gcx>>
+    {
+        match instance {
+            ty::InstanceDef::Item(did) if true => self.item_mir(did),
+            _ => queries::mir_shims::get(self, DUMMY_SP, instance).borrow(),
+        }
+    }
+
     /// Given the DefId of an item, returns its MIR, borrowed immutably.
     /// Returns None if there is no MIR for the DefId
     pub fn maybe_item_mir(self, did: DefId) -> Option<Ref<'gcx, Mir<'gcx>>> {
index fd95724990941337035ec75a3614b20479051044..1d816d342c4fd3f3b53f7c9046bf0c431d3af3e8 100644 (file)
@@ -398,6 +398,16 @@ pub fn closure_base_def_id(&self, def_id: DefId) -> DefId {
         }
         def_id
     }
+
+    /// Given the def-id of some item that has no type parameters, make
+    /// a suitable "empty substs" for it.
+    pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx ty::Substs<'tcx> {
+        ty::Substs::for_item(self, item_def_id,
+                             |_, _| self.mk_region(ty::ReErased),
+                             |_, _| {
+            bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
+        })
+    }
 }
 
 pub struct TypeIdHasher<'a, 'gcx: 'a+'tcx, 'tcx: 'a, W> {
index b15c1873f9bd84506dbe3cd7b3f5946bf83dad59..7f95f07f48d4ab3d6f062abb33a4aff6046ba779 100644 (file)
@@ -15,6 +15,7 @@
 use rustc_data_structures::bitslice::bits_to_string;
 use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_mir::util as mir_util;
 
 use dot;
 use dot::IntoCow;
@@ -219,7 +220,7 @@ fn chunked_present_left<W:io::Write>(w: &mut W,
             }
             Ok(())
         }
-        ::rustc_mir::graphviz::write_node_label(
+        mir_util::write_graphviz_node_label(
             *n, self.mbcx.mir(), &mut v, 4,
             |w| {
                 let flow = self.mbcx.flow_state();
index 7888a56d39dfbd5a5b3757160009e73acf2d7e61..da8aa231ccf157219d590059189e279d4e3605a8 100644 (file)
 use rustc_data_structures::bitslice::{BitwiseOperator};
 use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_mir::util::elaborate_drops::DropFlagState;
 
 use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
 use super::super::MoveDataParamEnv;
-use super::super::DropFlagState;
 use super::super::drop_flag_effects_for_function_entry;
 use super::super::drop_flag_effects_for_location;
 use super::super::on_lookup_result_bits;
index a71d23e7e1e7ecf98a717219448c53dc0e8fd4fd..88ec86cc95d614dfe461a30620d73dc6c5c9a064 100644 (file)
 use super::dataflow::{DataflowResults};
 use super::{drop_flag_effects_for_location, on_all_children_bits};
 use super::on_lookup_result_bits;
-use super::{DropFlagState, MoveDataParamEnv};
-use super::patch::MirPatch;
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::{Kind, Subst, Substs};
-use rustc::ty::util::IntTypeExt;
+use super::MoveDataParamEnv;
+use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::mir::transform::{Pass, MirPass, MirSource};
 use rustc::middle::const_val::ConstVal;
-use rustc::middle::lang_items;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_mir::util::patch::MirPatch;
+use rustc_mir::util::elaborate_drops::{DropFlagState, elaborate_drop};
+use rustc_mir::util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
 use syntax_pos::Span;
 
 use std::fmt;
-use std::iter;
 use std::u32;
 
 pub struct ElaborateDrops;
@@ -109,12 +107,116 @@ fn state(&self, path: MovePathIndex) -> (bool, bool) {
     }
 }
 
-impl fmt::Debug for InitializationData {
+struct Elaborator<'a, 'b: 'a, 'tcx: 'b> {
+    init_data: &'a InitializationData,
+    ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>,
+}
+
+impl<'a, 'b, 'tcx> fmt::Debug for Elaborator<'a, 'b, 'tcx> {
     fn fmt(&self, _f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
         Ok(())
     }
 }
 
+impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
+    type Path = MovePathIndex;
+
+    fn patch(&mut self) -> &mut MirPatch<'tcx> {
+        &mut self.ctxt.patch
+    }
+
+    fn mir(&self) -> &'a Mir<'tcx> {
+        self.ctxt.mir
+    }
+
+    fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> {
+        self.ctxt.tcx
+    }
+
+    fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> {
+        self.ctxt.param_env()
+    }
+
+    fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle {
+        let ((maybe_live, maybe_dead), multipart) = match mode {
+            DropFlagMode::Shallow => (self.init_data.state(path), false),
+            DropFlagMode::Deep => {
+                let mut some_live = false;
+                let mut some_dead = false;
+                let mut children_count = 0;
+                on_all_children_bits(
+                    self.tcx(), self.mir(), self.ctxt.move_data(),
+                    path, |child| {
+                        if self.ctxt.path_needs_drop(child) {
+                            let (live, dead) = self.init_data.state(child);
+                            debug!("elaborate_drop: state({:?}) = {:?}",
+                                   child, (live, dead));
+                            some_live |= live;
+                            some_dead |= dead;
+                            children_count += 1;
+                        }
+                    });
+                ((some_live, some_dead), children_count != 1)
+            }
+        };
+        match (maybe_live, maybe_dead, multipart) {
+            (false, _, _) => DropStyle::Dead,
+            (true, false, _) => DropStyle::Static,
+            (true, true, false) => DropStyle::Conditional,
+            (true, true, true) => DropStyle::Open,
+        }
+    }
+
+    fn clear_drop_flag(&mut self, loc: Location, path: Self::Path, mode: DropFlagMode) {
+        match mode {
+            DropFlagMode::Shallow => {
+                self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent);
+            }
+            DropFlagMode::Deep => {
+                on_all_children_bits(
+                    self.tcx(), self.mir(), self.ctxt.move_data(), path,
+                    |child| self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent)
+                 );
+            }
+        }
+    }
+
+    fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path> {
+        super::move_path_children_matching(self.ctxt.move_data(), path, |p| {
+            match p {
+                &Projection {
+                    elem: ProjectionElem::Field(idx, _), ..
+                } => idx == field,
+                _ => false
+            }
+        })
+    }
+
+    fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
+        super::move_path_children_matching(self.ctxt.move_data(), path, |p| {
+            match p {
+                &Projection { elem: ProjectionElem::Deref, .. } => true,
+                _ => false
+            }
+        })
+    }
+
+    fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path> {
+        super::move_path_children_matching(self.ctxt.move_data(), path, |p| {
+            match p {
+                &Projection {
+                    elem: ProjectionElem::Downcast(_, idx), ..
+                } => idx == variant,
+                _ => false
+            }
+        })
+    }
+
+    fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>> {
+        self.ctxt.drop_flag(path).map(Operand::Consume)
+    }
+}
+
 struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
@@ -125,19 +227,6 @@ struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
     patch: MirPatch<'tcx>,
 }
 
-#[derive(Copy, Clone, Debug)]
-struct DropCtxt<'a, 'tcx: 'a> {
-    source_info: SourceInfo,
-    is_cleanup: bool,
-
-    init_data: &'a InitializationData,
-
-    lvalue: &'a Lvalue<'tcx>,
-    path: MovePathIndex,
-    succ: BasicBlock,
-    unwind: Option<BasicBlock>
-}
-
 impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     fn move_data(&self) -> &'b MoveData<'tcx> { &self.env.move_data }
     fn param_env(&self) -> &'b ty::ParameterEnvironment<'tcx> {
@@ -254,19 +343,22 @@ fn elaborate_drops(&mut self)
                     let init_data = self.initialization_data_at(loc);
                     match self.move_data().rev_lookup.find(location) {
                         LookupResult::Exact(path) => {
-                            self.elaborate_drop(&DropCtxt {
-                                source_info: terminator.source_info,
-                                is_cleanup: data.is_cleanup,
-                                init_data: &init_data,
-                                lvalue: location,
-                                path: path,
-                                succ: target,
-                                unwind: if data.is_cleanup {
+                            elaborate_drop(
+                                &mut Elaborator {
+                                    init_data: &init_data,
+                                    ctxt: self
+                                },
+                                terminator.source_info,
+                                data.is_cleanup,
+                                location,
+                                path,
+                                target,
+                                if data.is_cleanup {
                                     None
                                 } else {
                                     Some(Option::unwrap_or(unwind, resume_block))
-                                }
-                            }, bb);
+                                },
+                                bb)
                         }
                         LookupResult::Parent(..) => {
                             span_bug!(terminator.source_info.span,
@@ -343,15 +435,18 @@ fn elaborate_replace(
                 debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path);
                 let init_data = self.initialization_data_at(loc);
 
-                self.elaborate_drop(&DropCtxt {
-                    source_info: terminator.source_info,
-                    is_cleanup: data.is_cleanup,
-                    init_data: &init_data,
-                    lvalue: location,
-                    path: path,
-                    succ: target,
-                    unwind: Some(unwind)
-                }, bb);
+                elaborate_drop(
+                    &mut Elaborator {
+                        init_data: &init_data,
+                        ctxt: self
+                    },
+                    terminator.source_info,
+                    data.is_cleanup,
+                    location,
+                    path,
+                    target,
+                    Some(unwind),
+                    bb);
                 on_all_children_bits(self.tcx, self.mir, self.move_data(), path, |child| {
                     self.set_drop_flag(Location { block: target, statement_index: 0 },
                                        child, DropFlagState::Present);
@@ -372,547 +467,6 @@ fn elaborate_replace(
         }
     }
 
-    /// This elaborates a single drop instruction, located at `bb`, and
-    /// patches over it.
-    ///
-    /// The elaborated drop checks the drop flags to only drop what
-    /// is initialized.
-    ///
-    /// In addition, the relevant drop flags also need to be cleared
-    /// to avoid double-drops. However, in the middle of a complex
-    /// drop, one must avoid clearing some of the flags before they
-    /// are read, as that would cause a memory leak.
-    ///
-    /// In particular, when dropping an ADT, multiple fields may be
-    /// joined together under the `rest` subpath. They are all controlled
-    /// by the primary drop flag, but only the last rest-field dropped
-    /// should clear it (and it must also not clear anything else).
-    ///
-    /// FIXME: I think we should just control the flags externally
-    /// and then we do not need this machinery.
-    fn elaborate_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>, bb: BasicBlock) {
-        debug!("elaborate_drop({:?})", c);
-
-        let mut some_live = false;
-        let mut some_dead = false;
-        let mut children_count = 0;
-        on_all_children_bits(
-            self.tcx, self.mir, self.move_data(),
-            c.path, |child| {
-                if self.path_needs_drop(child) {
-                    let (live, dead) = c.init_data.state(child);
-                    debug!("elaborate_drop: state({:?}) = {:?}",
-                           child, (live, dead));
-                    some_live |= live;
-                    some_dead |= dead;
-                    children_count += 1;
-                }
-            });
-
-        debug!("elaborate_drop({:?}): live - {:?}", c,
-               (some_live, some_dead));
-        match (some_live, some_dead) {
-            (false, false) | (false, true) => {
-                // dead drop - patch it out
-                self.patch.patch_terminator(bb, TerminatorKind::Goto {
-                    target: c.succ
-                });
-            }
-            (true, false) => {
-                // static drop - just set the flag
-                self.patch.patch_terminator(bb, TerminatorKind::Drop {
-                    location: c.lvalue.clone(),
-                    target: c.succ,
-                    unwind: c.unwind
-                });
-                self.drop_flags_for_drop(c, bb);
-            }
-            (true, true) => {
-                // dynamic drop
-                let drop_bb = if children_count == 1 || self.must_complete_drop(c) {
-                    self.conditional_drop(c)
-                } else {
-                    self.open_drop(c)
-                };
-                self.patch.patch_terminator(bb, TerminatorKind::Goto {
-                    target: drop_bb
-                });
-            }
-        }
-    }
-
-    /// Return the lvalue and move path for each field of `variant`,
-    /// (the move path is `None` if the field is a rest field).
-    fn move_paths_for_fields(&self,
-                             base_lv: &Lvalue<'tcx>,
-                             variant_path: MovePathIndex,
-                             variant: &'tcx ty::VariantDef,
-                             substs: &'tcx Substs<'tcx>)
-                             -> Vec<(Lvalue<'tcx>, Option<MovePathIndex>)>
-    {
-        variant.fields.iter().enumerate().map(|(i, f)| {
-            let subpath =
-                super::move_path_children_matching(self.move_data(), variant_path, |p| {
-                    match p {
-                        &Projection {
-                            elem: ProjectionElem::Field(idx, _), ..
-                        } => idx.index() == i,
-                        _ => false
-                    }
-                });
-
-            let field_ty =
-                self.tcx.normalize_associated_type_in_env(
-                    &f.ty(self.tcx, substs),
-                    self.param_env()
-                );
-            (base_lv.clone().field(Field::new(i), field_ty), subpath)
-        }).collect()
-    }
-
-    /// Create one-half of the drop ladder for a list of fields, and return
-    /// the list of steps in it in reverse order.
-    ///
-    /// `unwind_ladder` is such a list of steps in reverse order,
-    /// which is called instead of the next step if the drop unwinds
-    /// (the first field is never reached). If it is `None`, all
-    /// unwind targets are left blank.
-    fn drop_halfladder<'a>(&mut self,
-                           c: &DropCtxt<'a, 'tcx>,
-                           unwind_ladder: Option<Vec<BasicBlock>>,
-                           succ: BasicBlock,
-                           fields: &[(Lvalue<'tcx>, Option<MovePathIndex>)],
-                           is_cleanup: bool)
-                           -> Vec<BasicBlock>
-    {
-        let mut unwind_succ = if is_cleanup {
-            None
-        } else {
-            c.unwind
-        };
-
-        let mut succ = self.new_block(
-            c, c.is_cleanup, TerminatorKind::Goto { target: succ }
-        );
-
-        // Always clear the "master" drop flag at the bottom of the
-        // ladder. This is needed because the "master" drop flag
-        // protects the ADT's discriminant, which is invalidated
-        // after the ADT is dropped.
-        self.set_drop_flag(
-            Location { block: succ, statement_index: 0 },
-            c.path,
-            DropFlagState::Absent
-        );
-
-        fields.iter().rev().enumerate().map(|(i, &(ref lv, path))| {
-            succ = if let Some(path) = path {
-                debug!("drop_ladder: for std field {} ({:?})", i, lv);
-
-                self.elaborated_drop_block(&DropCtxt {
-                    source_info: c.source_info,
-                    is_cleanup: is_cleanup,
-                    init_data: c.init_data,
-                    lvalue: lv,
-                    path: path,
-                    succ: succ,
-                    unwind: unwind_succ,
-                })
-            } else {
-                debug!("drop_ladder: for rest field {} ({:?})", i, lv);
-
-                self.complete_drop(&DropCtxt {
-                    source_info: c.source_info,
-                    is_cleanup: is_cleanup,
-                    init_data: c.init_data,
-                    lvalue: lv,
-                    path: c.path,
-                    succ: succ,
-                    unwind: unwind_succ,
-                }, false)
-            };
-
-            unwind_succ = unwind_ladder.as_ref().map(|p| p[i]);
-            succ
-        }).collect()
-    }
-
-    /// Create a full drop ladder, consisting of 2 connected half-drop-ladders
-    ///
-    /// For example, with 3 fields, the drop ladder is
-    ///
-    /// .d0:
-    ///     ELAB(drop location.0 [target=.d1, unwind=.c1])
-    /// .d1:
-    ///     ELAB(drop location.1 [target=.d2, unwind=.c2])
-    /// .d2:
-    ///     ELAB(drop location.2 [target=`c.succ`, unwind=`c.unwind`])
-    /// .c1:
-    ///     ELAB(drop location.1 [target=.c2])
-    /// .c2:
-    ///     ELAB(drop location.2 [target=`c.unwind])
-    fn drop_ladder<'a>(&mut self,
-                       c: &DropCtxt<'a, 'tcx>,
-                       fields: Vec<(Lvalue<'tcx>, Option<MovePathIndex>)>)
-                       -> BasicBlock
-    {
-        debug!("drop_ladder({:?}, {:?})", c, fields);
-
-        let mut fields = fields;
-        fields.retain(|&(ref lvalue, _)| {
-            let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
-            self.tcx.type_needs_drop_given_env(ty, self.param_env())
-        });
-
-        debug!("drop_ladder - fields needing drop: {:?}", fields);
-
-        let unwind_ladder = if c.is_cleanup {
-            None
-        } else {
-            Some(self.drop_halfladder(c, None, c.unwind.unwrap(), &fields, true))
-        };
-
-        self.drop_halfladder(c, unwind_ladder, c.succ, &fields, c.is_cleanup)
-            .last().cloned().unwrap_or(c.succ)
-    }
-
-    fn open_drop_for_tuple<'a>(&mut self, c: &DropCtxt<'a, 'tcx>, tys: &[Ty<'tcx>])
-                               -> BasicBlock
-    {
-        debug!("open_drop_for_tuple({:?}, {:?})", c, tys);
-
-        let fields = tys.iter().enumerate().map(|(i, &ty)| {
-            (c.lvalue.clone().field(Field::new(i), ty),
-             super::move_path_children_matching(
-                 self.move_data(), c.path, |proj| match proj {
-                     &Projection {
-                         elem: ProjectionElem::Field(f, _), ..
-                     } => f.index() == i,
-                     _ => false
-                 }
-            ))
-        }).collect();
-
-        self.drop_ladder(c, fields)
-    }
-
-    fn open_drop_for_box<'a>(&mut self, c: &DropCtxt<'a, 'tcx>, ty: Ty<'tcx>)
-                             -> BasicBlock
-    {
-        debug!("open_drop_for_box({:?}, {:?})", c, ty);
-
-        let interior_path = super::move_path_children_matching(
-            self.move_data(), c.path, |proj| match proj {
-                &Projection { elem: ProjectionElem::Deref, .. } => true,
-                _ => false
-            }).unwrap();
-
-        let interior = c.lvalue.clone().deref();
-        let inner_c = DropCtxt {
-            lvalue: &interior,
-            unwind: c.unwind.map(|u| {
-                self.box_free_block(c, ty, u, true)
-            }),
-            succ: self.box_free_block(c, ty, c.succ, c.is_cleanup),
-            path: interior_path,
-            ..*c
-        };
-
-        self.elaborated_drop_block(&inner_c)
-    }
-
-    fn open_drop_for_adt<'a>(&mut self, c: &DropCtxt<'a, 'tcx>,
-                             adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>)
-                             -> BasicBlock {
-        debug!("open_drop_for_adt({:?}, {:?}, {:?})", c, adt, substs);
-
-        match adt.variants.len() {
-            1 => {
-                let fields = self.move_paths_for_fields(
-                    c.lvalue,
-                    c.path,
-                    &adt.variants[0],
-                    substs
-                );
-                self.drop_ladder(c, fields)
-            }
-            _ => {
-                let mut values = Vec::with_capacity(adt.variants.len());
-                let mut blocks = Vec::with_capacity(adt.variants.len());
-                let mut otherwise = None;
-                for (variant_index, discr) in adt.discriminants(self.tcx).enumerate() {
-                    let subpath = super::move_path_children_matching(
-                        self.move_data(), c.path, |proj| match proj {
-                            &Projection {
-                                elem: ProjectionElem::Downcast(_, idx), ..
-                            } => idx == variant_index,
-                            _ => false
-                        });
-                    if let Some(variant_path) = subpath {
-                        let base_lv = c.lvalue.clone().elem(
-                            ProjectionElem::Downcast(adt, variant_index)
-                        );
-                        let fields = self.move_paths_for_fields(
-                            &base_lv,
-                            variant_path,
-                            &adt.variants[variant_index],
-                            substs);
-                        values.push(discr);
-                        blocks.push(self.drop_ladder(c, fields));
-                    } else {
-                        // variant not found - drop the entire enum
-                        if let None = otherwise {
-                            otherwise = Some(self.complete_drop(c, true));
-                        }
-                    }
-                }
-                if let Some(block) = otherwise {
-                    blocks.push(block);
-                } else {
-                    values.pop();
-                }
-                // If there are multiple variants, then if something
-                // is present within the enum the discriminant, tracked
-                // by the rest path, must be initialized.
-                //
-                // Additionally, we do not want to switch on the
-                // discriminant after it is free-ed, because that
-                // way lies only trouble.
-                let discr_ty = adt.repr.discr_type().to_ty(self.tcx);
-                let discr = Lvalue::Local(self.patch.new_temp(discr_ty));
-                let switch_block = self.patch.new_block(BasicBlockData {
-                    statements: vec![
-                        Statement {
-                            source_info: c.source_info,
-                            kind: StatementKind::Assign(discr.clone(),
-                                                        Rvalue::Discriminant(c.lvalue.clone()))
-                        }
-                    ],
-                    terminator: Some(Terminator {
-                        source_info: c.source_info,
-                        kind: TerminatorKind::SwitchInt {
-                            discr: Operand::Consume(discr),
-                            switch_ty: discr_ty,
-                            values: From::from(values),
-                            targets: blocks,
-                        }
-                    }),
-                    is_cleanup: c.is_cleanup,
-                });
-                self.drop_flag_test_block(c, switch_block)
-            }
-        }
-    }
-
-    /// The slow-path - create an "open", elaborated drop for a type
-    /// which is moved-out-of only partially, and patch `bb` to a jump
-    /// to it. This must not be called on ADTs with a destructor,
-    /// as these can't be moved-out-of, except for `Box<T>`, which is
-    /// special-cased.
-    ///
-    /// This creates a "drop ladder" that drops the needed fields of the
-    /// ADT, both in the success case or if one of the destructors fail.
-    fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
-        let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
-        match ty.sty {
-            ty::TyClosure(def_id, substs) => {
-                let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx).collect();
-                self.open_drop_for_tuple(c, &tys)
-            }
-            ty::TyTuple(tys, _) => {
-                self.open_drop_for_tuple(c, tys)
-            }
-            ty::TyAdt(def, _) if def.is_box() => {
-                self.open_drop_for_box(c, ty.boxed_ty())
-            }
-            ty::TyAdt(def, substs) => {
-                self.open_drop_for_adt(c, def, substs)
-            }
-            _ => bug!("open drop from non-ADT `{:?}`", ty)
-        }
-    }
-
-    /// Return a basic block that drop an lvalue using the context
-    /// and path in `c`. If `update_drop_flag` is true, also
-    /// clear `c`.
-    ///
-    /// if FLAG(c.path)
-    ///     if(update_drop_flag) FLAG(c.path) = false
-    ///     drop(c.lv)
-    fn complete_drop<'a>(
-        &mut self,
-        c: &DropCtxt<'a, 'tcx>,
-        update_drop_flag: bool)
-        -> BasicBlock
-    {
-        debug!("complete_drop({:?},{:?})", c, update_drop_flag);
-
-        let drop_block = self.drop_block(c);
-        if update_drop_flag {
-            self.set_drop_flag(
-                Location { block: drop_block, statement_index: 0 },
-                c.path,
-                DropFlagState::Absent
-            );
-        }
-
-        self.drop_flag_test_block(c, drop_block)
-    }
-
-    /// Create a simple conditional drop.
-    ///
-    /// if FLAG(c.lv)
-    ///     FLAGS(c.lv) = false
-    ///     drop(c.lv)
-    fn conditional_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>)
-                            -> BasicBlock
-    {
-        debug!("conditional_drop({:?})", c);
-        let drop_bb = self.drop_block(c);
-        self.drop_flags_for_drop(c, drop_bb);
-
-        self.drop_flag_test_block(c, drop_bb)
-    }
-
-    fn new_block<'a>(&mut self,
-                     c: &DropCtxt<'a, 'tcx>,
-                     is_cleanup: bool,
-                     k: TerminatorKind<'tcx>)
-                     -> BasicBlock
-    {
-        self.patch.new_block(BasicBlockData {
-            statements: vec![],
-            terminator: Some(Terminator {
-                source_info: c.source_info, kind: k
-            }),
-            is_cleanup: is_cleanup
-        })
-    }
-
-    fn elaborated_drop_block<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
-        debug!("elaborated_drop_block({:?})", c);
-        let blk = self.drop_block(c);
-        self.elaborate_drop(c, blk);
-        blk
-    }
-
-    fn drop_flag_test_block<'a>(&mut self,
-                                c: &DropCtxt<'a, 'tcx>,
-                                on_set: BasicBlock)
-                                -> BasicBlock {
-        self.drop_flag_test_block_with_succ(c, c.is_cleanup, on_set, c.succ)
-    }
-
-    fn drop_flag_test_block_with_succ<'a>(&mut self,
-                                          c: &DropCtxt<'a, 'tcx>,
-                                          is_cleanup: bool,
-                                          on_set: BasicBlock,
-                                          on_unset: BasicBlock)
-                                          -> BasicBlock
-    {
-        let (maybe_live, maybe_dead) = c.init_data.state(c.path);
-        debug!("drop_flag_test_block({:?},{:?},{:?}) - {:?}",
-               c, is_cleanup, on_set, (maybe_live, maybe_dead));
-
-        match (maybe_live, maybe_dead) {
-            (false, _) => on_unset,
-            (true, false) => on_set,
-            (true, true) => {
-                let flag = self.drop_flag(c.path).unwrap();
-                let term = TerminatorKind::if_(self.tcx, Operand::Consume(flag), on_set, on_unset);
-                self.new_block(c, is_cleanup, term)
-            }
-        }
-    }
-
-    fn drop_block<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
-        self.new_block(c, c.is_cleanup, TerminatorKind::Drop {
-            location: c.lvalue.clone(),
-            target: c.succ,
-            unwind: c.unwind
-        })
-    }
-
-    fn box_free_block<'a>(
-        &mut self,
-        c: &DropCtxt<'a, 'tcx>,
-        ty: Ty<'tcx>,
-        target: BasicBlock,
-        is_cleanup: bool
-    ) -> BasicBlock {
-        let block = self.unelaborated_free_block(c, ty, target, is_cleanup);
-        self.drop_flag_test_block_with_succ(c, is_cleanup, block, target)
-    }
-
-    fn unelaborated_free_block<'a>(
-        &mut self,
-        c: &DropCtxt<'a, 'tcx>,
-        ty: Ty<'tcx>,
-        target: BasicBlock,
-        is_cleanup: bool
-    ) -> BasicBlock {
-        let mut statements = vec![];
-        if let Some(&flag) = self.drop_flags.get(&c.path) {
-            statements.push(Statement {
-                source_info: c.source_info,
-                kind: StatementKind::Assign(
-                    Lvalue::Local(flag),
-                    self.constant_bool(c.source_info.span, false)
-                )
-            });
-        }
-
-        let tcx = self.tcx;
-        let unit_temp = Lvalue::Local(self.patch.new_temp(tcx.mk_nil()));
-        let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
-        let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
-        let fty = tcx.item_type(free_func).subst(tcx, substs);
-
-        self.patch.new_block(BasicBlockData {
-            statements: statements,
-            terminator: Some(Terminator {
-                source_info: c.source_info, kind: TerminatorKind::Call {
-                    func: Operand::Constant(Constant {
-                        span: c.source_info.span,
-                        ty: fty,
-                        literal: Literal::Item {
-                            def_id: free_func,
-                            substs: substs
-                        }
-                    }),
-                    args: vec![Operand::Consume(c.lvalue.clone())],
-                    destination: Some((unit_temp, target)),
-                    cleanup: None
-                }
-            }),
-            is_cleanup: is_cleanup
-        })
-    }
-
-    fn must_complete_drop<'a>(&self, c: &DropCtxt<'a, 'tcx>) -> bool {
-        // if we have a destuctor, we must *not* split the drop.
-
-        // dataflow can create unneeded children in some cases
-        // - be sure to ignore them.
-
-        let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
-
-        match ty.sty {
-            ty::TyAdt(def, _) => {
-                if def.has_dtor(self.tcx) && !def.is_box() {
-                    self.tcx.sess.span_warn(
-                        c.source_info.span,
-                        &format!("dataflow bug??? moving out of type with dtor {:?}",
-                                 c));
-                    true
-                } else {
-                    false
-                }
-            }
-            _ => false
-        }
-    }
-
     fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
         Rvalue::Use(Operand::Constant(Constant {
             span: span,
@@ -1023,15 +577,4 @@ fn drop_flags_for_locs(&mut self) {
             }
         }
     }
-
-    fn drop_flags_for_drop<'a>(&mut self,
-                               c: &DropCtxt<'a, 'tcx>,
-                               bb: BasicBlock)
-    {
-        let loc = self.patch.terminator_loc(self.mir, bb);
-        on_all_children_bits(
-            self.tcx, self.mir, self.move_data(), c.path,
-            |child| self.set_drop_flag(loc, child, DropFlagState::Absent)
-        );
-    }
 }
index 8d866676dbd1875dc3838da2e0491e4db397ae00..81037fe40d9dab07ecdfd904a5a492c5a72b15a1 100644 (file)
@@ -437,7 +437,7 @@ fn gather_rvalue(&mut self, loc: Location, rvalue: &Rvalue<'tcx>) {
             }
             Rvalue::Ref(..) |
             Rvalue::Discriminant(..) |
-            Rvalue::Len(..) => {}
+            Rvalue::Len(..) |
             Rvalue::Box(..) => {
                 // This returns an rvalue with uninitialized contents. We can't
                 // move out of it here because it is an rvalue - assignments always
index 1c9ee335699ae13439d689cbb1af77e826b72b69..9237bb31f6bd7f62c267550d29723c46d69bcf13 100644 (file)
 use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location};
 use rustc::session::Session;
 use rustc::ty::{self, TyCtxt};
+use rustc_mir::util::elaborate_drops::DropFlagState;
 
 mod abs_domain;
 pub mod elaborate_drops;
 mod dataflow;
 mod gather_moves;
-mod patch;
 // mod graphviz;
 
 use self::dataflow::{BitDenotation};
@@ -183,21 +183,6 @@ fn process_terminator(&mut self, bb: BasicBlock, term: &Option<Terminator<'tcx>>
     }
 }
 
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
-enum DropFlagState {
-    Present, // i.e. initialized
-    Absent, // i.e. deinitialized or "moved"
-}
-
-impl DropFlagState {
-    fn value(self) -> bool {
-        match self {
-            DropFlagState::Present => true,
-            DropFlagState::Absent => false
-        }
-    }
-}
-
 fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
                                         path: MovePathIndex,
                                         mut cond: F)
diff --git a/src/librustc_borrowck/borrowck/mir/patch.rs b/src/librustc_borrowck/borrowck/mir/patch.rs
deleted file mode 100644 (file)
index 19f240d..0000000
+++ /dev/null
@@ -1,178 +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.
-
-use rustc::ty::Ty;
-use rustc::mir::*;
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
-
-/// This struct represents a patch to MIR, which can add
-/// new statements and basic blocks and patch over block
-/// terminators.
-pub struct MirPatch<'tcx> {
-    patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
-    new_blocks: Vec<BasicBlockData<'tcx>>,
-    new_statements: Vec<(Location, StatementKind<'tcx>)>,
-    new_locals: Vec<LocalDecl<'tcx>>,
-    resume_block: BasicBlock,
-    next_local: usize,
-}
-
-impl<'tcx> MirPatch<'tcx> {
-    pub fn new(mir: &Mir<'tcx>) -> Self {
-        let mut result = MirPatch {
-            patch_map: IndexVec::from_elem(None, mir.basic_blocks()),
-            new_blocks: vec![],
-            new_statements: vec![],
-            new_locals: vec![],
-            next_local: mir.local_decls.len(),
-            resume_block: START_BLOCK
-        };
-
-        // make sure the MIR we create has a resume block. It is
-        // completely legal to convert jumps to the resume block
-        // to jumps to None, but we occasionally have to add
-        // instructions just before that.
-
-        let mut resume_block = None;
-        let mut resume_stmt_block = None;
-        for (bb, block) in mir.basic_blocks().iter_enumerated() {
-            if let TerminatorKind::Resume = block.terminator().kind {
-                if block.statements.len() > 0 {
-                    resume_stmt_block = Some(bb);
-                } else {
-                    resume_block = Some(bb);
-                }
-                break
-            }
-        }
-        let resume_block = resume_block.unwrap_or_else(|| {
-            result.new_block(BasicBlockData {
-                statements: vec![],
-                terminator: Some(Terminator {
-                    source_info: SourceInfo {
-                        span: mir.span,
-                        scope: ARGUMENT_VISIBILITY_SCOPE
-                    },
-                    kind: TerminatorKind::Resume
-                }),
-                is_cleanup: true
-            })});
-        result.resume_block = resume_block;
-        if let Some(resume_stmt_block) = resume_stmt_block {
-            result.patch_terminator(resume_stmt_block, TerminatorKind::Goto {
-                target: resume_block
-            });
-        }
-        result
-    }
-
-    pub fn resume_block(&self) -> BasicBlock {
-        self.resume_block
-    }
-
-    pub fn is_patched(&self, bb: BasicBlock) -> bool {
-        self.patch_map[bb].is_some()
-    }
-
-    pub fn terminator_loc(&self, mir: &Mir<'tcx>, bb: BasicBlock) -> Location {
-        let offset = match bb.index().checked_sub(mir.basic_blocks().len()) {
-            Some(index) => self.new_blocks[index].statements.len(),
-            None => mir[bb].statements.len()
-        };
-        Location {
-            block: bb,
-            statement_index: offset
-        }
-    }
-
-    pub fn new_temp(&mut self, ty: Ty<'tcx>) -> Local {
-        let index = self.next_local;
-        self.next_local += 1;
-        self.new_locals.push(LocalDecl::new_temp(ty));
-        Local::new(index as usize)
-    }
-
-    pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
-        let block = BasicBlock::new(self.patch_map.len());
-        debug!("MirPatch: new_block: {:?}: {:?}", block, data);
-        self.new_blocks.push(data);
-        self.patch_map.push(None);
-        block
-    }
-
-    pub fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) {
-        assert!(self.patch_map[block].is_none());
-        debug!("MirPatch: patch_terminator({:?}, {:?})", block, new);
-        self.patch_map[block] = Some(new);
-    }
-
-    pub fn add_statement(&mut self, loc: Location, stmt: StatementKind<'tcx>) {
-        debug!("MirPatch: add_statement({:?}, {:?})", loc, stmt);
-        self.new_statements.push((loc, stmt));
-    }
-
-    pub fn add_assign(&mut self, loc: Location, lv: Lvalue<'tcx>, rv: Rvalue<'tcx>) {
-        self.add_statement(loc, StatementKind::Assign(lv, rv));
-    }
-
-    pub fn apply(self, mir: &mut Mir<'tcx>) {
-        debug!("MirPatch: {:?} new temps, starting from index {}: {:?}",
-               self.new_locals.len(), mir.local_decls.len(), self.new_locals);
-        debug!("MirPatch: {} new blocks, starting from index {}",
-               self.new_blocks.len(), mir.basic_blocks().len());
-        mir.basic_blocks_mut().extend(self.new_blocks);
-        mir.local_decls.extend(self.new_locals);
-        for (src, patch) in self.patch_map.into_iter_enumerated() {
-            if let Some(patch) = patch {
-                debug!("MirPatch: patching block {:?}", src);
-                mir[src].terminator_mut().kind = patch;
-            }
-        }
-
-        let mut new_statements = self.new_statements;
-        new_statements.sort_by(|u,v| u.0.cmp(&v.0));
-
-        let mut delta = 0;
-        let mut last_bb = START_BLOCK;
-        for (mut loc, stmt) in new_statements {
-            if loc.block != last_bb {
-                delta = 0;
-                last_bb = loc.block;
-            }
-            debug!("MirPatch: adding statement {:?} at loc {:?}+{}",
-                   stmt, loc, delta);
-            loc.statement_index += delta;
-            let source_info = Self::source_info_for_index(
-                &mir[loc.block], loc
-            );
-            mir[loc.block].statements.insert(
-                loc.statement_index, Statement {
-                    source_info: source_info,
-                    kind: stmt
-                });
-            delta += 1;
-        }
-    }
-
-    pub fn source_info_for_index(data: &BasicBlockData, loc: Location) -> SourceInfo {
-        match data.statements.get(loc.statement_index) {
-            Some(stmt) => stmt.source_info,
-            None => data.terminator().source_info
-        }
-    }
-
-    pub fn source_info_for_location(&self, mir: &Mir, loc: Location) -> SourceInfo {
-        let data = match loc.block.index().checked_sub(mir.basic_blocks().len()) {
-            Some(new) => &self.new_blocks[new],
-            None => &mir[loc.block]
-        };
-        Self::source_info_for_index(data, loc)
-    }
-}
index 9937cbbf8e10c3929293c99e1cf1bdb7d3d3d4b9..60eef8dd3bc5fac2f45e0521901ed0a270465f2f 100644 (file)
@@ -16,7 +16,7 @@
 register_long_diagnostics! {
 
 E0001: r##"
-## Note: this error code is no longer emitted by the compiler.
+#### Note: this error code is no longer emitted by the compiler.
 
 This error suggests that the expression arm corresponding to the noted pattern
 will never be reached as for all possible values of the expression being
@@ -43,7 +43,7 @@
 "##,
 
 E0002: r##"
-## Note: this error code is no longer emitted by the compiler.
+#### Note: this error code is no longer emitted by the compiler.
 
 This error indicates that an empty match expression is invalid because the type
 it is matching on is non-empty (there exist values of this type). In safe code
@@ -75,7 +75,7 @@ fn foo(x: Option<String>) {
 "##,
 
 E0003: r##"
-## Note: this error code is no longer emitted by the compiler.
+#### Note: this error code is no longer emitted by the compiler.
 
 Not-a-Number (NaN) values cannot be compared for equality and hence can never
 match the input to a match expression. So, the following will not compile:
index b6978478085d5b224607c90a0acc898c17ad712b..6cd97e9559885048ac4f6905ecc257b5bf45e545 100644 (file)
@@ -26,8 +26,7 @@
 use rustc_borrowck as borrowck;
 use rustc_borrowck::graphviz as borrowck_dot;
 
-use rustc_mir::pretty::write_mir_pretty;
-use rustc_mir::graphviz::write_mir_graphviz;
+use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};
 
 use syntax::ast::{self, BlockCheckMode};
 use syntax::fold::{self, Folder};
index 906c4b7256fdc56c45e35e77502918681f5918aa..0a8719c1253299c4c52d3e0b93c090073f8a5adf 100644 (file)
@@ -25,7 +25,7 @@
 #![feature(core_intrinsics)]
 #![feature(conservative_impl_trait)]
 #![cfg_attr(stage0,feature(field_init_shorthand))]
-#![feature(pub_restricted)]
+#![cfg_attr(stage0, feature(pub_restricted))]
 
 extern crate graphviz;
 #[macro_use] extern crate rustc;
index 0c31e30671dc2678abdaae6d93030e836139d04c..044ed529ef74cfa50c96f36683172d5a04999174 100644 (file)
@@ -293,7 +293,7 @@ fn encode_enum_variant_info(&mut self,
             predicates: Some(self.encode_predicates(def_id)),
 
             ast: None,
-            mir: None,
+            mir: self.encode_mir(def_id),
         }
     }
 
@@ -426,7 +426,7 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
             predicates: Some(self.encode_predicates(def_id)),
 
             ast: None,
-            mir: None,
+            mir: self.encode_mir(def_id),
         }
     }
 
index dab85106873299e2747b79e954f36c2c41941620..e1b0c6a6f042e0ee980b39d05688b45e4277958b 100644 (file)
@@ -40,7 +40,19 @@ pub fn into_expr(&mut self,
                 this.in_scope(extent, block, |this| this.into(destination, block, value))
             }
             ExprKind::Block { body: ast_block } => {
-                this.ast_block(destination, block, ast_block)
+                if let Some(_) = ast_block.break_to_expr_id {
+                    // This is a `break`-able block (currently only `catch { ... }`)
+                    let exit_block = this.cfg.start_new_block();
+                    let block_exit = this.in_breakable_scope(None, exit_block,
+                                                             destination.clone(), |this| {
+                        this.ast_block(destination, block, ast_block)
+                    });
+                    this.cfg.terminate(unpack!(block_exit), source_info,
+                                       TerminatorKind::Goto { target: exit_block });
+                    exit_block.unit()
+                } else {
+                    this.ast_block(destination, block, ast_block)
+                }
             }
             ExprKind::Match { discriminant, arms } => {
                 this.match_expr(destination, expr_span, block, discriminant, arms)
@@ -165,8 +177,8 @@ pub fn into_expr(&mut self,
                 this.cfg.terminate(block, source_info,
                                    TerminatorKind::Goto { target: loop_block });
 
-                this.in_loop_scope(
-                    loop_block, exit_block, destination.clone(),
+                this.in_breakable_scope(
+                    Some(loop_block), exit_block, destination.clone(),
                     move |this| {
                         // conduct the test, if necessary
                         let body_block;
index be39dcbf6d08d84a3940a32188dffb6838710cfb..7336da654c1840f550e82d5b66ffc125bd7454ac 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use build::{BlockAnd, BlockAndExtension, Builder};
-use build::scope::LoopScope;
+use build::scope::BreakableScope;
 use hair::*;
 use rustc::mir::*;
 
@@ -77,19 +77,21 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
                 block.unit()
             }
             ExprKind::Continue { label } => {
-                let LoopScope { continue_block, extent, .. } =
-                    *this.find_loop_scope(expr_span, label);
+                let BreakableScope { continue_block, extent, .. } =
+                    *this.find_breakable_scope(expr_span, label);
+                let continue_block = continue_block.expect(
+                    "Attempted to continue in non-continuable breakable block");
                 this.exit_scope(expr_span, extent, block, continue_block);
                 this.cfg.start_new_block().unit()
             }
             ExprKind::Break { label, value } => {
                 let (break_block, extent, destination) = {
-                    let LoopScope {
+                    let BreakableScope {
                         break_block,
                         extent,
                         ref break_destination,
                         ..
-                    } = *this.find_loop_scope(expr_span, label);
+                    } = *this.find_breakable_scope(expr_span, label);
                     (break_block, extent, break_destination.clone())
                 };
                 if let Some(value) = value {
index 41374a0012327a4e78cb7d49e1b9682b682c2890..db03a1c68f7156023cde3ad4c0b631b71036fb41 100644 (file)
@@ -36,9 +36,9 @@ pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// see the `scope` module for more details
     scopes: Vec<scope::Scope<'tcx>>,
 
-    /// the current set of loops; see the `scope` module for more
+    /// the current set of breakables; see the `scope` module for more
     /// details
-    loop_scopes: Vec<scope::LoopScope<'tcx>>,
+    breakable_scopes: Vec<scope::BreakableScope<'tcx>>,
 
     /// the vector of all scopes that we have created thus far;
     /// we track this for debuginfo later
@@ -248,7 +248,7 @@ fn new(hir: Cx<'a, 'gcx, 'tcx>,
             scopes: vec![],
             visibility_scopes: IndexVec::new(),
             visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
-            loop_scopes: vec![],
+            breakable_scopes: vec![],
             local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty), 1),
             var_indices: NodeMap(),
             unit_temp: None,
index 3dab1717f6b2e4a466534457c6eb971435eef903..1de5b9218564fdb73a96682b9fb3dc291c540392 100644 (file)
@@ -177,16 +177,16 @@ struct FreeData<'tcx> {
 }
 
 #[derive(Clone, Debug)]
-pub struct LoopScope<'tcx> {
+pub struct BreakableScope<'tcx> {
     /// Extent of the loop
     pub extent: CodeExtent,
-    /// Where the body of the loop begins
-    pub continue_block: BasicBlock,
-    /// Block to branch into when the loop terminates (either by being `break`-en out from, or by
-    /// having its condition to become false)
+    /// Where the body of the loop begins. `None` if block
+    pub continue_block: Option<BasicBlock>,
+    /// Block to branch into when the loop or block terminates (either by being `break`-en out
+    /// from, or by having its condition to become false)
     pub break_block: BasicBlock,
-    /// The destination of the loop expression itself (i.e. where to put the result of a `break`
-    /// expression)
+    /// The destination of the loop/block expression itself (i.e. where to put the result of a
+    /// `break` expression)
     pub break_destination: Lvalue<'tcx>,
 }
 
@@ -242,28 +242,29 @@ fn source_info(&self, span: Span) -> SourceInfo {
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     // Adding and removing scopes
     // ==========================
-    /// Start a loop scope, which tracks where `continue` and `break`
+    /// Start a breakable scope, which tracks where `continue` and `break`
     /// should branch to. See module comment for more details.
     ///
-    /// Returns the might_break attribute of the LoopScope used.
-    pub fn in_loop_scope<F>(&mut self,
-                            loop_block: BasicBlock,
+    /// Returns the might_break attribute of the BreakableScope used.
+    pub fn in_breakable_scope<F, R>(&mut self,
+                            loop_block: Option<BasicBlock>,
                             break_block: BasicBlock,
                             break_destination: Lvalue<'tcx>,
-                            f: F)
-        where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>)
+                            f: F) -> R
+        where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> R
     {
         let extent = self.topmost_scope();
-        let loop_scope = LoopScope {
+        let scope = BreakableScope {
             extent: extent,
             continue_block: loop_block,
             break_block: break_block,
             break_destination: break_destination,
         };
-        self.loop_scopes.push(loop_scope);
-        f(self);
-        let loop_scope = self.loop_scopes.pop().unwrap();
-        assert!(loop_scope.extent == extent);
+        self.breakable_scopes.push(scope);
+        let res = f(self);
+        let breakable_scope = self.breakable_scopes.pop().unwrap();
+        assert!(breakable_scope.extent == extent);
+        res
     }
 
     /// Convenience wrapper that pushes a scope and then executes `f`
@@ -381,18 +382,18 @@ pub fn new_visibility_scope(&mut self, span: Span) -> VisibilityScope {
 
     // Finding scopes
     // ==============
-    /// Finds the loop scope for a given label. This is used for
+    /// Finds the breakable scope for a given label. This is used for
     /// resolving `break` and `continue`.
-    pub fn find_loop_scope(&mut self,
+    pub fn find_breakable_scope(&mut self,
                            span: Span,
                            label: CodeExtent)
-                           -> &mut LoopScope<'tcx> {
+                           -> &mut BreakableScope<'tcx> {
         // find the loop-scope with the correct id
-        self.loop_scopes.iter_mut()
+        self.breakable_scopes.iter_mut()
             .rev()
-            .filter(|loop_scope| loop_scope.extent == label)
+            .filter(|breakable_scope| breakable_scope.extent == label)
             .next()
-            .unwrap_or_else(|| span_bug!(span, "no enclosing loop scope found?"))
+            .unwrap_or_else(|| span_bug!(span, "no enclosing breakable scope found"))
     }
 
     /// Given a span and the current visibility scope, make a SourceInfo.
diff --git a/src/librustc_mir/def_use.rs b/src/librustc_mir/def_use.rs
deleted file mode 100644 (file)
index d20d50c..0000000
+++ /dev/null
@@ -1,163 +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.
-
-//! Def-use analysis.
-
-use rustc::mir::{Local, Location, Lvalue, Mir};
-use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor};
-use rustc_data_structures::indexed_vec::IndexVec;
-use std::marker::PhantomData;
-use std::mem;
-
-pub struct DefUseAnalysis<'tcx> {
-    info: IndexVec<Local, Info<'tcx>>,
-}
-
-#[derive(Clone)]
-pub struct Info<'tcx> {
-    pub defs_and_uses: Vec<Use<'tcx>>,
-}
-
-#[derive(Clone)]
-pub struct Use<'tcx> {
-    pub context: LvalueContext<'tcx>,
-    pub location: Location,
-}
-
-impl<'tcx> DefUseAnalysis<'tcx> {
-    pub fn new(mir: &Mir<'tcx>) -> DefUseAnalysis<'tcx> {
-        DefUseAnalysis {
-            info: IndexVec::from_elem_n(Info::new(), mir.local_decls.len()),
-        }
-    }
-
-    pub fn analyze(&mut self, mir: &Mir<'tcx>) {
-        let mut finder = DefUseFinder {
-            info: mem::replace(&mut self.info, IndexVec::new()),
-        };
-        finder.visit_mir(mir);
-        self.info = finder.info
-    }
-
-    pub fn local_info(&self, local: Local) -> &Info<'tcx> {
-        &self.info[local]
-    }
-
-    pub fn local_info_mut(&mut self, local: Local) -> &mut Info<'tcx> {
-        &mut self.info[local]
-    }
-
-    fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'tcx>, mut callback: F)
-                               where F: for<'a> FnMut(&'a mut Lvalue<'tcx>,
-                                                      LvalueContext<'tcx>,
-                                                      Location) {
-        for lvalue_use in &self.info[local].defs_and_uses {
-            MutateUseVisitor::new(local,
-                                  &mut callback,
-                                  mir).visit_location(mir, lvalue_use.location)
-        }
-    }
-
-    /// FIXME(pcwalton): This should update the def-use chains.
-    pub fn replace_all_defs_and_uses_with(&self,
-                                          local: Local,
-                                          mir: &mut Mir<'tcx>,
-                                          new_lvalue: Lvalue<'tcx>) {
-        self.mutate_defs_and_uses(local, mir, |lvalue, _, _| *lvalue = new_lvalue.clone())
-    }
-}
-
-struct DefUseFinder<'tcx> {
-    info: IndexVec<Local, Info<'tcx>>,
-}
-
-impl<'tcx> DefUseFinder<'tcx> {
-    fn lvalue_mut_info(&mut self, lvalue: &Lvalue<'tcx>) -> Option<&mut Info<'tcx>> {
-        let info = &mut self.info;
-
-        if let Lvalue::Local(local) = *lvalue {
-            Some(&mut info[local])
-        } else {
-            None
-        }
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for DefUseFinder<'tcx> {
-    fn visit_lvalue(&mut self,
-                    lvalue: &Lvalue<'tcx>,
-                    context: LvalueContext<'tcx>,
-                    location: Location) {
-        if let Some(ref mut info) = self.lvalue_mut_info(lvalue) {
-            info.defs_and_uses.push(Use {
-                context: context,
-                location: location,
-            })
-        }
-        self.super_lvalue(lvalue, context, location)
-    }
-}
-
-impl<'tcx> Info<'tcx> {
-    fn new() -> Info<'tcx> {
-        Info {
-            defs_and_uses: vec![],
-        }
-    }
-
-    pub fn def_count(&self) -> usize {
-        self.defs_and_uses.iter().filter(|lvalue_use| lvalue_use.context.is_mutating_use()).count()
-    }
-
-    pub fn def_count_not_including_drop(&self) -> usize {
-        self.defs_and_uses.iter().filter(|lvalue_use| {
-            lvalue_use.context.is_mutating_use() && !lvalue_use.context.is_drop()
-        }).count()
-    }
-
-    pub fn use_count(&self) -> usize {
-        self.defs_and_uses.iter().filter(|lvalue_use| {
-            lvalue_use.context.is_nonmutating_use()
-        }).count()
-    }
-}
-
-struct MutateUseVisitor<'tcx, F> {
-    query: Local,
-    callback: F,
-    phantom: PhantomData<&'tcx ()>,
-}
-
-impl<'tcx, F> MutateUseVisitor<'tcx, F> {
-    fn new(query: Local, callback: F, _: &Mir<'tcx>)
-           -> MutateUseVisitor<'tcx, F>
-           where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) {
-        MutateUseVisitor {
-            query: query,
-            callback: callback,
-            phantom: PhantomData,
-        }
-    }
-}
-
-impl<'tcx, F> MutVisitor<'tcx> for MutateUseVisitor<'tcx, F>
-              where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) {
-    fn visit_lvalue(&mut self,
-                    lvalue: &mut Lvalue<'tcx>,
-                    context: LvalueContext<'tcx>,
-                    location: Location) {
-        if let Lvalue::Local(local) = *lvalue {
-            if local == self.query {
-                (self.callback)(lvalue, context, location)
-            }
-        }
-        self.super_lvalue(lvalue, context, location)
-    }
-}
diff --git a/src/librustc_mir/graphviz.rs b/src/librustc_mir/graphviz.rs
deleted file mode 100644 (file)
index 91600b9..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use dot;
-use rustc::hir::def_id::DefId;
-use rustc::mir::*;
-use rustc::ty::TyCtxt;
-use std::fmt::Debug;
-use std::io::{self, Write};
-use syntax::ast::NodeId;
-
-use rustc_data_structures::indexed_vec::Idx;
-
-/// Write a graphviz DOT graph of a list of MIRs.
-pub fn write_mir_graphviz<'a, 'b, 'tcx, W, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
-                                              iter: I,
-                                              w: &mut W)
-                                              -> io::Result<()>
-    where W: Write, I: Iterator<Item=DefId>
-{
-    for def_id in iter {
-        let nodeid = tcx.hir.as_local_node_id(def_id).unwrap();
-        let mir = &tcx.item_mir(def_id);
-
-        writeln!(w, "digraph Mir_{} {{", nodeid)?;
-
-        // Global graph properties
-        writeln!(w, r#"    graph [fontname="monospace"];"#)?;
-        writeln!(w, r#"    node [fontname="monospace"];"#)?;
-        writeln!(w, r#"    edge [fontname="monospace"];"#)?;
-
-        // Graph label
-        write_graph_label(tcx, nodeid, mir, w)?;
-
-        // Nodes
-        for (block, _) in mir.basic_blocks().iter_enumerated() {
-            write_node(block, mir, w)?;
-        }
-
-        // Edges
-        for (source, _) in mir.basic_blocks().iter_enumerated() {
-            write_edges(source, mir, w)?;
-        }
-        writeln!(w, "}}")?
-    }
-    Ok(())
-}
-
-/// Write a graphviz HTML-styled label for the given basic block, with
-/// all necessary escaping already performed. (This is suitable for
-/// emitting directly, as is done in this module, or for use with the
-/// LabelText::HtmlStr from libgraphviz.)
-///
-/// `init` and `fini` are callbacks for emitting additional rows of
-/// data (using HTML enclosed with `<tr>` in the emitted text).
-pub fn write_node_label<W: Write, INIT, FINI>(block: BasicBlock,
-                                              mir: &Mir,
-                                              w: &mut W,
-                                              num_cols: u32,
-                                              init: INIT,
-                                              fini: FINI) -> io::Result<()>
-    where INIT: Fn(&mut W) -> io::Result<()>,
-          FINI: Fn(&mut W) -> io::Result<()>
-{
-    let data = &mir[block];
-
-    write!(w, r#"<table border="0" cellborder="1" cellspacing="0">"#)?;
-
-    // Basic block number at the top.
-    write!(w, r#"<tr><td {attrs} colspan="{colspan}">{blk}</td></tr>"#,
-           attrs=r#"bgcolor="gray" align="center""#,
-           colspan=num_cols,
-           blk=block.index())?;
-
-    init(w)?;
-
-    // List of statements in the middle.
-    if !data.statements.is_empty() {
-        write!(w, r#"<tr><td align="left" balign="left">"#)?;
-        for statement in &data.statements {
-            write!(w, "{}<br/>", escape(statement))?;
-        }
-        write!(w, "</td></tr>")?;
-    }
-
-    // Terminator head at the bottom, not including the list of successor blocks. Those will be
-    // displayed as labels on the edges between blocks.
-    let mut terminator_head = String::new();
-    data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
-    write!(w, r#"<tr><td align="left">{}</td></tr>"#, dot::escape_html(&terminator_head))?;
-
-    fini(w)?;
-
-    // Close the table
-    writeln!(w, "</table>")
-}
-
-/// Write a graphviz DOT node for the given basic block.
-fn write_node<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
-    // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
-    write!(w, r#"    {} [shape="none", label=<"#, node(block))?;
-    write_node_label(block, mir, w, 1, |_| Ok(()), |_| Ok(()))?;
-    // Close the node label and the node itself.
-    writeln!(w, ">];")
-}
-
-/// Write graphviz DOT edges with labels between the given basic block and all of its successors.
-fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
-    let terminator = mir[source].terminator();
-    let labels = terminator.kind.fmt_successor_labels();
-
-    for (&target, label) in terminator.successors().iter().zip(labels) {
-        writeln!(w, r#"    {} -> {} [label="{}"];"#, node(source), node(target), label)?;
-    }
-
-    Ok(())
-}
-
-/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
-/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
-/// all the variables and temporaries.
-fn write_graph_label<'a, 'tcx, W: Write>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                         nid: NodeId,
-                                         mir: &Mir,
-                                         w: &mut W)
-                                         -> io::Result<()> {
-    write!(w, "    label=<fn {}(", dot::escape_html(&tcx.node_path_str(nid)))?;
-
-    // fn argument types.
-    for (i, arg) in mir.args_iter().enumerate() {
-        if i > 0 {
-            write!(w, ", ")?;
-        }
-        write!(w, "{:?}: {}", Lvalue::Local(arg), escape(&mir.local_decls[arg].ty))?;
-    }
-
-    write!(w, ") -&gt; {}", escape(mir.return_ty))?;
-    write!(w, r#"<br align="left"/>"#)?;
-
-    for local in mir.vars_and_temps_iter() {
-        let decl = &mir.local_decls[local];
-
-        write!(w, "let ")?;
-        if decl.mutability == Mutability::Mut {
-            write!(w, "mut ")?;
-        }
-
-        if let Some(name) = decl.name {
-            write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
-                   Lvalue::Local(local), escape(&decl.ty), name)?;
-        } else {
-            write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
-                   Lvalue::Local(local), escape(&decl.ty))?;
-        }
-    }
-
-    writeln!(w, ">;")
-}
-
-fn node(block: BasicBlock) -> String {
-    format!("bb{}", block.index())
-}
-
-fn escape<T: Debug>(t: &T) -> String {
-    dot::escape_html(&format!("{:?}", t))
-}
index c67bb8ec6c585346fc7d646addcecfaeda46df6f..da58a1ed1f49b2a90c5f72b1fd4f7da63cd0b9b5 100644 (file)
@@ -606,22 +606,25 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             }
         }
         hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() },
-        hir::ExprBreak(label, ref value) => {
-            match label.loop_id.into() {
-                Ok(loop_id) => ExprKind::Break {
-                    label: cx.tcx.region_maps.node_extent(loop_id),
+        hir::ExprBreak(dest, ref value) => {
+            match dest.target_id {
+                hir::ScopeTarget::Block(target_id) |
+                hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(target_id)) => ExprKind::Break {
+                    label: cx.tcx.region_maps.node_extent(target_id),
                     value: value.to_ref(),
                 },
-                Err(err) => bug!("invalid loop id for break: {}", err)
+                hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
+                    bug!("invalid loop id for break: {}", err)
             }
-
         }
-        hir::ExprAgain(label) => {
-            match label.loop_id.into() {
-                Ok(loop_id) => ExprKind::Continue {
+        hir::ExprAgain(dest) => {
+            match dest.target_id {
+                hir::ScopeTarget::Block(_) => bug!("cannot continue to blocks"),
+                hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => ExprKind::Continue {
                     label: cx.tcx.region_maps.node_extent(loop_id),
                 },
-                Err(err) => bug!("invalid loop id for continue: {}", err)
+                hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
+                    bug!("invalid loop id for continue: {}", err)
             }
         }
         hir::ExprMatch(ref discr, ref arms, _) => {
index f21f1881c832e17212dea3ee392641ce0d68589a..590c6a430b98a2862970c58db9c28c8282bc50d5 100644 (file)
@@ -22,6 +22,8 @@
 
 #![feature(associated_consts)]
 #![feature(box_patterns)]
+#![feature(box_syntax)]
+#![cfg_attr(stage0, feature(field_init_shorthand))]
 #![feature(i128_type)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 
 pub mod build;
 pub mod callgraph;
-pub mod def_use;
-pub mod graphviz;
 mod hair;
+mod shim;
 pub mod mir_map;
-pub mod pretty;
 pub mod transform;
+pub mod util;
 
 use rustc::ty::maps::Providers;
 
 pub fn provide(providers: &mut Providers) {
     mir_map::provide(providers);
+    shim::provide(providers);
     transform::qualify_consts::provide(providers);
 }
\ No newline at end of file
index 58f23a5c81bd7fa1cc9f557bf0aab1a994b0cb40..8c138d779c10687f274897e635476808e1227de5 100644 (file)
 use rustc::mir::Mir;
 use rustc::mir::transform::MirSource;
 use rustc::mir::visit::MutVisitor;
-use pretty;
+use shim;
 use hair::cx::Cx;
+use util as mir_util;
 
 use rustc::traits::Reveal;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::ty::subst::Substs;
 use rustc::hir;
+use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use syntax::abi::Abi;
 use syntax::ast;
 use syntax_pos::Span;
@@ -44,6 +46,31 @@ fn build_mir_for_crate_task<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (): ()) {
         tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
             tcx.item_mir(body_owner_def_id);
         });
+
+        // Tuple struct/variant constructors don't have a BodyId, so we need
+        // to build them separately.
+        struct GatherCtors<'a, 'tcx: 'a> {
+            tcx: TyCtxt<'a, 'tcx, 'tcx>
+        }
+        impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> {
+            fn visit_variant_data(&mut self,
+                                  v: &'tcx hir::VariantData,
+                                  _: ast::Name,
+                                  _: &'tcx hir::Generics,
+                                  _: ast::NodeId,
+                                  _: Span) {
+                if let hir::VariantData::Tuple(_, node_id) = *v {
+                    self.tcx.item_mir(self.tcx.hir.local_def_id(node_id));
+                }
+                intravisit::walk_struct_def(self, v)
+            }
+            fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
+                NestedVisitorMap::None
+            }
+        }
+        tcx.visit_all_item_likes_in_krate(DepNode::Mir, &mut GatherCtors {
+            tcx: tcx
+        }.as_deep_visitor());
     }
 }
 
@@ -95,6 +122,10 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
                 _ => hir::BodyId { node_id: expr.id }
             }
         }
+        hir::map::NodeVariant(variant) =>
+            return create_constructor_shim(tcx, id, &variant.node.data),
+        hir::map::NodeStructCtor(ctor) =>
+            return create_constructor_shim(tcx, id, ctor),
         _ => unsupported()
     };
 
@@ -144,7 +175,7 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
             mem::transmute::<Mir, Mir<'tcx>>(mir)
         };
 
-        pretty::dump_mir(tcx, "mir_map", &0, src, &mir);
+        mir_util::dump_mir(tcx, "mir_map", &0, src, &mir);
 
         tcx.alloc_mir(mir)
     })
@@ -180,6 +211,38 @@ fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>) {
     }
 }
 
+fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     ctor_id: ast::NodeId,
+                                     v: &'tcx hir::VariantData)
+                                     -> &'tcx RefCell<Mir<'tcx>>
+{
+    let span = tcx.hir.span(ctor_id);
+    if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
+        let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
+        tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
+            let (mut mir, src) =
+                shim::build_adt_ctor(&infcx, ctor_id, fields, span);
+
+            // Convert the Mir to global types.
+            let tcx = infcx.tcx.global_tcx();
+            let mut globalizer = GlobalizeMir {
+                tcx: tcx,
+                span: mir.span
+            };
+            globalizer.visit_mir(&mut mir);
+            let mir = unsafe {
+                mem::transmute::<Mir, Mir<'tcx>>(mir)
+            };
+
+            mir_util::dump_mir(tcx, "mir_map", &0, src, &mir);
+
+            tcx.alloc_mir(mir)
+        })
+    } else {
+        span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
 
@@ -189,12 +252,9 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              -> Ty<'tcx> {
     let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
 
-    // We're just hard-coding the idea that the signature will be
-    // &self or &mut self and hence will have a bound region with
-    // number 0, hokey.
     let region = ty::Region::ReFree(ty::FreeRegion {
         scope: tcx.region_maps.item_extent(body_id.node_id),
-        bound_region: ty::BoundRegion::BrAnon(0),
+        bound_region: ty::BoundRegion::BrEnv,
     });
     let region = tcx.mk_region(region);
 
diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs
deleted file mode 100644 (file)
index 35734dc..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::mir::*;
-use rustc::mir::transform::MirSource;
-use rustc::ty::TyCtxt;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::indexed_vec::{Idx};
-use std::fmt::Display;
-use std::fs;
-use std::io::{self, Write};
-use std::path::{PathBuf, Path};
-
-const INDENT: &'static str = "    ";
-/// Alignment for lining up comments following MIR statements
-const ALIGN: usize = 40;
-
-/// If the session is properly configured, dumps a human-readable
-/// representation of the mir into:
-///
-/// ```text
-/// rustc.node<node_id>.<pass_name>.<disambiguator>
-/// ```
-///
-/// Output from this function is controlled by passing `-Z dump-mir=<filter>`,
-/// where `<filter>` takes the following forms:
-///
-/// - `all` -- dump MIR for all fns, all passes, all everything
-/// - `substring1&substring2,...` -- `&`-separated list of substrings
-///   that can appear in the pass-name or the `item_path_str` for the given
-///   node-id. If any one of the substrings match, the data is dumped out.
-pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          pass_name: &str,
-                          disambiguator: &Display,
-                          src: MirSource,
-                          mir: &Mir<'tcx>) {
-    let filters = match tcx.sess.opts.debugging_opts.dump_mir {
-        None => return,
-        Some(ref filters) => filters,
-    };
-    let node_id = src.item_id();
-    let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id));
-    let is_matched =
-        filters.split("&")
-               .any(|filter| {
-                   filter == "all" ||
-                       pass_name.contains(filter) ||
-                       node_path.contains(filter)
-               });
-    if !is_matched {
-        return;
-    }
-
-    let promotion_id = match src {
-        MirSource::Promoted(_, id) => format!("-{:?}", id),
-        _ => String::new()
-    };
-
-    let mut file_path = PathBuf::new();
-    if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
-        let p = Path::new(file_dir);
-        file_path.push(p);
-    };
-    let file_name = format!("rustc.node{}{}.{}.{}.mir",
-                            node_id, promotion_id, pass_name, disambiguator);
-    file_path.push(&file_name);
-    let _ = fs::File::create(&file_path).and_then(|mut file| {
-        writeln!(file, "// MIR for `{}`", node_path)?;
-        writeln!(file, "// node_id = {}", node_id)?;
-        writeln!(file, "// pass_name = {}", pass_name)?;
-        writeln!(file, "// disambiguator = {}", disambiguator)?;
-        writeln!(file, "")?;
-        write_mir_fn(tcx, src, mir, &mut file)?;
-        Ok(())
-    });
-}
-
-/// Write out a human-readable textual representation for the given MIR.
-pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
-                                         iter: I,
-                                         w: &mut Write)
-                                         -> io::Result<()>
-    where I: Iterator<Item=DefId>, 'tcx: 'a
-{
-    let mut first = true;
-    for def_id in iter.filter(DefId::is_local) {
-        let mir = &tcx.item_mir(def_id);
-
-        if first {
-            first = false;
-        } else {
-            // Put empty lines between all items
-            writeln!(w, "")?;
-        }
-
-        let id = tcx.hir.as_local_node_id(def_id).unwrap();
-        let src = MirSource::from_node(tcx, id);
-        write_mir_fn(tcx, src, mir, w)?;
-
-        for (i, mir) in mir.promoted.iter_enumerated() {
-            writeln!(w, "")?;
-            write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w)?;
-        }
-    }
-    Ok(())
-}
-
-pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              src: MirSource,
-                              mir: &Mir<'tcx>,
-                              w: &mut Write)
-                              -> io::Result<()> {
-    write_mir_intro(tcx, src, mir, w)?;
-    for block in mir.basic_blocks().indices() {
-        write_basic_block(tcx, block, mir, w)?;
-        if block.index() + 1 != mir.basic_blocks().len() {
-            writeln!(w, "")?;
-        }
-    }
-
-    writeln!(w, "}}")?;
-    Ok(())
-}
-
-/// Write out a human-readable textual representation for the given basic block.
-fn write_basic_block(tcx: TyCtxt,
-                     block: BasicBlock,
-                     mir: &Mir,
-                     w: &mut Write)
-                     -> io::Result<()> {
-    let data = &mir[block];
-
-    // Basic block label at the top.
-    writeln!(w, "{}{:?}: {{", INDENT, block)?;
-
-    // List of statements in the middle.
-    let mut current_location = Location { block: block, statement_index: 0 };
-    for statement in &data.statements {
-        let indented_mir = format!("{0}{0}{1:?};", INDENT, statement);
-        writeln!(w, "{0:1$} // {2}",
-                 indented_mir,
-                 ALIGN,
-                 comment(tcx, statement.source_info))?;
-
-        current_location.statement_index += 1;
-    }
-
-    // Terminator at the bottom.
-    let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind);
-    writeln!(w, "{0:1$} // {2}",
-             indented_terminator,
-             ALIGN,
-             comment(tcx, data.terminator().source_info))?;
-
-    writeln!(w, "{}}}", INDENT)
-}
-
-fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String {
-    format!("scope {} at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
-}
-
-/// Prints user-defined variables in a scope tree.
-///
-/// Returns the total number of variables printed.
-fn write_scope_tree(tcx: TyCtxt,
-                    mir: &Mir,
-                    scope_tree: &FxHashMap<VisibilityScope, Vec<VisibilityScope>>,
-                    w: &mut Write,
-                    parent: VisibilityScope,
-                    depth: usize)
-                    -> io::Result<()> {
-    let indent = depth * INDENT.len();
-
-    let children = match scope_tree.get(&parent) {
-        Some(childs) => childs,
-        None => return Ok(()),
-    };
-
-    for &child in children {
-        let data = &mir.visibility_scopes[child];
-        assert_eq!(data.parent_scope, Some(parent));
-        writeln!(w, "{0:1$}scope {2} {{", "", indent, child.index())?;
-
-        // User variable types (including the user's name in a comment).
-        for local in mir.vars_iter() {
-            let var = &mir.local_decls[local];
-            let (name, source_info) = if var.source_info.unwrap().scope == child {
-                (var.name.unwrap(), var.source_info.unwrap())
-            } else {
-                // Not a variable or not declared in this scope.
-                continue;
-            };
-
-            let mut_str = if var.mutability == Mutability::Mut {
-                "mut "
-            } else {
-                ""
-            };
-
-            let indent = indent + INDENT.len();
-            let indented_var = format!("{0:1$}let {2}{3:?}: {4};",
-                                       INDENT,
-                                       indent,
-                                       mut_str,
-                                       local,
-                                       var.ty);
-            writeln!(w, "{0:1$} // \"{2}\" in {3}",
-                     indented_var,
-                     ALIGN,
-                     name,
-                     comment(tcx, source_info))?;
-        }
-
-        write_scope_tree(tcx, mir, scope_tree, w, child, depth + 1)?;
-
-        writeln!(w, "{0:1$}}}", "", depth * INDENT.len())?;
-    }
-
-    Ok(())
-}
-
-/// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
-/// local variables (both user-defined bindings and compiler temporaries).
-fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             src: MirSource,
-                             mir: &Mir,
-                             w: &mut Write)
-                             -> io::Result<()> {
-    write_mir_sig(tcx, src, mir, w)?;
-    writeln!(w, " {{")?;
-
-    // construct a scope tree and write it out
-    let mut scope_tree: FxHashMap<VisibilityScope, Vec<VisibilityScope>> = FxHashMap();
-    for (index, scope_data) in mir.visibility_scopes.iter().enumerate() {
-        if let Some(parent) = scope_data.parent_scope {
-            scope_tree.entry(parent)
-                      .or_insert(vec![])
-                      .push(VisibilityScope::new(index));
-        } else {
-            // Only the argument scope has no parent, because it's the root.
-            assert_eq!(index, ARGUMENT_VISIBILITY_SCOPE.index());
-        }
-    }
-
-    // Print return pointer
-    let indented_retptr = format!("{}let mut {:?}: {};",
-                                  INDENT,
-                                  RETURN_POINTER,
-                                  mir.return_ty);
-    writeln!(w, "{0:1$} // return pointer",
-             indented_retptr,
-             ALIGN)?;
-
-    write_scope_tree(tcx, mir, &scope_tree, w, ARGUMENT_VISIBILITY_SCOPE, 1)?;
-
-    write_temp_decls(mir, w)?;
-
-    // Add an empty line before the first block is printed.
-    writeln!(w, "")?;
-
-    Ok(())
-}
-
-fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
-                 -> io::Result<()>
-{
-    match src {
-        MirSource::Fn(_) => write!(w, "fn")?,
-        MirSource::Const(_) => write!(w, "const")?,
-        MirSource::Static(_, hir::MutImmutable) => write!(w, "static")?,
-        MirSource::Static(_, hir::MutMutable) => write!(w, "static mut")?,
-        MirSource::Promoted(_, i) => write!(w, "{:?} in", i)?
-    }
-
-    write!(w, " {}", tcx.node_path_str(src.item_id()))?;
-
-    if let MirSource::Fn(_) = src {
-        write!(w, "(")?;
-
-        // fn argument types.
-        for (i, arg) in mir.args_iter().enumerate() {
-            if i != 0 {
-                write!(w, ", ")?;
-            }
-            write!(w, "{:?}: {}", Lvalue::Local(arg), mir.local_decls[arg].ty)?;
-        }
-
-        write!(w, ") -> {}", mir.return_ty)
-    } else {
-        assert_eq!(mir.arg_count, 0);
-        write!(w, ": {} =", mir.return_ty)
-    }
-}
-
-fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
-    // Compiler-introduced temporary types.
-    for temp in mir.temps_iter() {
-        writeln!(w, "{}let mut {:?}: {};", INDENT, temp, mir.local_decls[temp].ty)?;
-    }
-
-    Ok(())
-}
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
new file mode 100644 (file)
index 0000000..26d5b7f
--- /dev/null
@@ -0,0 +1,489 @@
+// 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.
+
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+use rustc::infer;
+use rustc::middle::region::ROOT_CODE_EXTENT;
+use rustc::mir::*;
+use rustc::mir::transform::MirSource;
+use rustc::ty::{self, Ty};
+use rustc::ty::subst::{Kind, Subst};
+use rustc::ty::maps::Providers;
+
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+
+use syntax::abi::Abi;
+use syntax::ast;
+use syntax_pos::Span;
+
+use std::cell::RefCell;
+use std::fmt;
+use std::iter;
+use std::mem;
+
+use transform::{add_call_guards, no_landing_pads, simplify};
+use util::elaborate_drops::{self, DropElaborator, DropStyle, DropFlagMode};
+use util::patch::MirPatch;
+
+pub fn provide(providers: &mut Providers) {
+    providers.mir_shims = make_shim;
+}
+
+fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+                       instance: ty::InstanceDef<'tcx>)
+                       -> &'tcx RefCell<Mir<'tcx>>
+{
+    debug!("make_shim({:?})", instance);
+    let did = instance.def_id();
+    let span = tcx.def_span(did);
+    let param_env =
+        tcx.construct_parameter_environment(span, did, ROOT_CODE_EXTENT);
+
+    let mut result = match instance {
+        ty::InstanceDef::Item(..) =>
+            bug!("item {:?} passed to make_shim", instance),
+        ty::InstanceDef::FnPtrShim(def_id, ty) => {
+            let trait_ = tcx.trait_of_item(def_id).unwrap();
+            let adjustment = match tcx.lang_items.fn_trait_kind(trait_) {
+                Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
+                Some(ty::ClosureKind::FnMut) |
+                Some(ty::ClosureKind::Fn) => Adjustment::Deref,
+                None => bug!("fn pointer {:?} is not an fn", ty)
+            };
+            // HACK: we need the "real" argument types for the MIR,
+            // but because our substs are (Self, Args), where Args
+            // is a tuple, we must include the *concrete* argument
+            // types in the MIR. They will be substituted again with
+            // the param-substs, but because they are concrete, this
+            // will not do any harm.
+            let sig = tcx.erase_late_bound_regions(&ty.fn_sig());
+            let arg_tys = sig.inputs();
+
+            build_call_shim(
+                tcx,
+                &param_env,
+                def_id,
+                adjustment,
+                CallKind::Indirect,
+                Some(arg_tys)
+            )
+        }
+        ty::InstanceDef::Virtual(def_id, _) => {
+            // We are translating a call back to our def-id, which
+            // trans::mir knows to turn to an actual virtual call.
+            build_call_shim(
+                tcx,
+                &param_env,
+                def_id,
+                Adjustment::Identity,
+                CallKind::Direct(def_id),
+                None
+            )
+        }
+        ty::InstanceDef::ClosureOnceShim { call_once } => {
+            let fn_mut = tcx.lang_items.fn_mut_trait().unwrap();
+            let call_mut = tcx.global_tcx()
+                .associated_items(fn_mut)
+                .find(|it| it.kind == ty::AssociatedKind::Method)
+                .unwrap().def_id;
+
+            build_call_shim(
+                tcx,
+                &param_env,
+                call_once,
+                Adjustment::RefMut,
+                CallKind::Direct(call_mut),
+                None
+            )
+        }
+        ty::InstanceDef::DropGlue(def_id, ty) => {
+            build_drop_shim(tcx, &param_env, def_id, ty)
+        }
+        ty::InstanceDef::Intrinsic(_) => {
+            bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
+        }
+    };
+        debug!("make_shim({:?}) = untransformed {:?}", instance, result);
+        no_landing_pads::no_landing_pads(tcx, &mut result);
+        simplify::simplify_cfg(&mut result);
+        add_call_guards::add_call_guards(&mut result);
+    debug!("make_shim({:?}) = {:?}", instance, result);
+
+    let result = tcx.alloc_mir(result);
+    // Perma-borrow MIR from shims to prevent mutation.
+    mem::forget(result.borrow());
+    result
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+enum Adjustment {
+    Identity,
+    Deref,
+    RefMut,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+enum CallKind {
+    Indirect,
+    Direct(DefId),
+}
+
+fn temp_decl(mutability: Mutability, ty: Ty) -> LocalDecl {
+    LocalDecl { mutability, ty, name: None, source_info: None }
+}
+
+fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>)
+    -> IndexVec<Local, LocalDecl<'tcx>>
+{
+    iter::once(temp_decl(Mutability::Mut, sig.output()))
+        .chain(sig.inputs().iter().map(
+            |ity| temp_decl(Mutability::Not, ity)))
+        .collect()
+}
+
+fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+                             param_env: &ty::ParameterEnvironment<'tcx>,
+                             def_id: DefId,
+                             ty: Option<Ty<'tcx>>)
+                             -> Mir<'tcx>
+{
+    debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
+
+    let substs = if let Some(ty) = ty {
+        tcx.mk_substs(iter::once(Kind::from(ty)))
+    } else {
+        param_env.free_substs
+    };
+    let fn_ty = tcx.item_type(def_id).subst(tcx, substs);
+    let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
+    let span = tcx.def_span(def_id);
+
+    let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE };
+
+    let return_block = BasicBlock::new(1);
+    let mut blocks = IndexVec::new();
+    let block = |blocks: &mut IndexVec<_, _>, kind| {
+        blocks.push(BasicBlockData {
+            statements: vec![],
+            terminator: Some(Terminator { source_info, kind }),
+            is_cleanup: false
+        })
+    };
+    block(&mut blocks, TerminatorKind::Goto { target: return_block });
+    block(&mut blocks, TerminatorKind::Return);
+
+    let mut mir = Mir::new(
+        blocks,
+        IndexVec::from_elem_n(
+            VisibilityScopeData { span: span, parent_scope: None }, 1
+        ),
+        IndexVec::new(),
+        sig.output(),
+        local_decls_for_sig(&sig),
+        sig.inputs().len(),
+        vec![],
+        span
+    );
+
+    if let Some(..) = ty {
+        let patch = {
+            let mut elaborator = DropShimElaborator {
+                mir: &mir,
+                patch: MirPatch::new(&mir),
+                tcx, param_env
+            };
+            let dropee = Lvalue::Projection(
+                box Projection {
+                    base: Lvalue::Local(Local::new(1+0)),
+                    elem: ProjectionElem::Deref
+                }
+                );
+            let resume_block = elaborator.patch.resume_block();
+            elaborate_drops::elaborate_drop(
+                &mut elaborator,
+                source_info,
+                false,
+                &dropee,
+                (),
+                return_block,
+                Some(resume_block),
+                START_BLOCK
+            );
+            elaborator.patch
+        };
+        patch.apply(&mut mir);
+    }
+
+    mir
+}
+
+pub struct DropShimElaborator<'a, 'tcx: 'a> {
+    mir: &'a Mir<'tcx>,
+    patch: MirPatch<'tcx>,
+    tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+    param_env: &'a ty::ParameterEnvironment<'tcx>,
+}
+
+impl<'a, 'tcx> fmt::Debug for DropShimElaborator<'a, 'tcx> {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        Ok(())
+    }
+}
+
+impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
+    type Path = ();
+
+    fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
+    fn mir(&self) -> &'a Mir<'tcx> { self.mir }
+    fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
+    fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> { self.param_env }
+
+    fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
+        if let DropFlagMode::Shallow = mode {
+            DropStyle::Static
+        } else {
+            DropStyle::Open
+        }
+    }
+
+    fn get_drop_flag(&mut self, _path: Self::Path) -> Option<Operand<'tcx>> {
+        None
+    }
+
+    fn clear_drop_flag(&mut self, _location: Location, _path: Self::Path, _mode: DropFlagMode) {
+    }
+
+    fn field_subpath(&self, _path: Self::Path, _field: Field) -> Option<Self::Path> {
+        None
+    }
+    fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
+        None
+    }
+    fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::Path> {
+        Some(())
+    }
+}
+
+/// Build a "call" shim for `def_id`. The shim calls the
+/// function specified by `call_kind`, first adjusting its first
+/// argument according to `rcvr_adjustment`.
+///
+/// If `untuple_args` is a vec of types, the second argument of the
+/// function will be untupled as these types.
+fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+                             param_env: &ty::ParameterEnvironment<'tcx>,
+                             def_id: DefId,
+                             rcvr_adjustment: Adjustment,
+                             call_kind: CallKind,
+                             untuple_args: Option<&[Ty<'tcx>]>)
+                             -> Mir<'tcx>
+{
+    debug!("build_call_shim(def_id={:?}, rcvr_adjustment={:?}, \
+            call_kind={:?}, untuple_args={:?})",
+           def_id, rcvr_adjustment, call_kind, untuple_args);
+
+    let fn_ty = tcx.item_type(def_id).subst(tcx, param_env.free_substs);
+    let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
+    let span = tcx.def_span(def_id);
+
+    debug!("build_call_shim: sig={:?}", sig);
+
+    let mut local_decls = local_decls_for_sig(&sig);
+    let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE };
+
+    let rcvr_arg = Local::new(1+0);
+    let rcvr_l = Lvalue::Local(rcvr_arg);
+    let mut statements = vec![];
+
+    let rcvr = match rcvr_adjustment {
+        Adjustment::Identity => Operand::Consume(rcvr_l),
+        Adjustment::Deref => Operand::Consume(Lvalue::Projection(
+            box Projection { base: rcvr_l, elem: ProjectionElem::Deref }
+        )),
+        Adjustment::RefMut => {
+            // let rcvr = &mut rcvr;
+            let re_erased = tcx.mk_region(ty::ReErased);
+            let ref_rcvr = local_decls.push(temp_decl(
+                Mutability::Not,
+                tcx.mk_ref(re_erased, ty::TypeAndMut {
+                    ty: sig.inputs()[0],
+                    mutbl: hir::Mutability::MutMutable
+                })
+            ));
+            statements.push(Statement {
+                source_info: source_info,
+                kind: StatementKind::Assign(
+                    Lvalue::Local(ref_rcvr),
+                    Rvalue::Ref(re_erased, BorrowKind::Mut, rcvr_l)
+                )
+            });
+            Operand::Consume(Lvalue::Local(ref_rcvr))
+        }
+    };
+
+    let (callee, mut args) = match call_kind {
+        CallKind::Indirect => (rcvr, vec![]),
+        CallKind::Direct(def_id) => (
+            Operand::Constant(Constant {
+                span: span,
+                ty: tcx.item_type(def_id).subst(tcx, param_env.free_substs),
+                literal: Literal::Item { def_id, substs: param_env.free_substs },
+            }),
+            vec![rcvr]
+        )
+    };
+
+    if let Some(untuple_args) = untuple_args {
+        args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
+            let arg_lv = Lvalue::Local(Local::new(1+1));
+            Operand::Consume(Lvalue::Projection(box Projection {
+                base: arg_lv,
+                elem: ProjectionElem::Field(Field::new(i), *ity)
+            }))
+        }));
+    } else {
+        args.extend((1..sig.inputs().len()).map(|i| {
+            Operand::Consume(Lvalue::Local(Local::new(1+i)))
+        }));
+    }
+
+    let mut blocks = IndexVec::new();
+    let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
+        blocks.push(BasicBlockData {
+            statements,
+            terminator: Some(Terminator { source_info, kind }),
+            is_cleanup
+        })
+    };
+
+    // BB #0
+    block(&mut blocks, statements, TerminatorKind::Call {
+        func: callee,
+        args: args,
+        destination: Some((Lvalue::Local(RETURN_POINTER),
+                           BasicBlock::new(1))),
+        cleanup: if let Adjustment::RefMut = rcvr_adjustment {
+            Some(BasicBlock::new(3))
+        } else {
+            None
+        }
+    }, false);
+
+    if let Adjustment::RefMut = rcvr_adjustment {
+        // BB #1 - drop for Self
+        block(&mut blocks, vec![], TerminatorKind::Drop {
+            location: Lvalue::Local(rcvr_arg),
+            target: BasicBlock::new(2),
+            unwind: None
+        }, false);
+    }
+    // BB #1/#2 - return
+    block(&mut blocks, vec![], TerminatorKind::Return, false);
+    if let Adjustment::RefMut = rcvr_adjustment {
+        // BB #3 - drop if closure panics
+        block(&mut blocks, vec![], TerminatorKind::Drop {
+            location: Lvalue::Local(rcvr_arg),
+            target: BasicBlock::new(4),
+            unwind: None
+        }, true);
+
+        // BB #4 - resume
+        block(&mut blocks, vec![], TerminatorKind::Resume, true);
+    }
+
+    let mut mir = Mir::new(
+        blocks,
+        IndexVec::from_elem_n(
+            VisibilityScopeData { span: span, parent_scope: None }, 1
+        ),
+        IndexVec::new(),
+        sig.output(),
+        local_decls,
+        sig.inputs().len(),
+        vec![],
+        span
+    );
+    if let Abi::RustCall = sig.abi {
+        mir.spread_arg = Some(Local::new(sig.inputs().len()));
+    }
+    mir
+}
+
+pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
+                                      ctor_id: ast::NodeId,
+                                      fields: &[hir::StructField],
+                                      span: Span)
+                                      -> (Mir<'tcx>, MirSource)
+{
+    let tcx = infcx.tcx;
+    let def_id = tcx.hir.local_def_id(ctor_id);
+    let sig = match tcx.item_type(def_id).sty {
+        ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty)
+            .expect("LBR in ADT constructor signature"),
+        _ => bug!("unexpected type for ctor {:?}", def_id)
+    };
+    let sig = tcx.erase_regions(&sig);
+
+    let (adt_def, substs) = match sig.output().sty {
+        ty::TyAdt(adt_def, substs) => (adt_def, substs),
+        _ => bug!("unexpected type for ADT ctor {:?}", sig.output())
+    };
+
+    debug!("build_ctor: def_id={:?} sig={:?} fields={:?}", def_id, sig, fields);
+
+    let local_decls = local_decls_for_sig(&sig);
+
+    let source_info = SourceInfo {
+        span: span,
+        scope: ARGUMENT_VISIBILITY_SCOPE
+    };
+
+    let variant_no = if adt_def.is_enum() {
+        adt_def.variant_index_with_id(def_id)
+    } else {
+        0
+    };
+
+    // return = ADT(arg0, arg1, ...); return
+    let start_block = BasicBlockData {
+        statements: vec![Statement {
+            source_info: source_info,
+            kind: StatementKind::Assign(
+                Lvalue::Local(RETURN_POINTER),
+                Rvalue::Aggregate(
+                    AggregateKind::Adt(adt_def, variant_no, substs, None),
+                    (1..sig.inputs().len()+1).map(|i| {
+                        Operand::Consume(Lvalue::Local(Local::new(i)))
+                    }).collect()
+                )
+            )
+        }],
+        terminator: Some(Terminator {
+            source_info: source_info,
+            kind: TerminatorKind::Return,
+        }),
+        is_cleanup: false
+    };
+
+    let mir = Mir::new(
+        IndexVec::from_elem_n(start_block, 1),
+        IndexVec::from_elem_n(
+            VisibilityScopeData { span: span, parent_scope: None }, 1
+        ),
+        IndexVec::new(),
+        sig.output(),
+        local_decls,
+        sig.inputs().len(),
+        vec![],
+        span
+    );
+    (mir, MirSource::Fn(ctor_id))
+}
index 89e644e4fb077d5398d94c61f1add1bd0e981f8a..80b17c6a008f5902334915c89c4677e99d6c0f82 100644 (file)
 
 impl<'tcx> MirPass<'tcx> for AddCallGuards {
     fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
-        let pred_count: IndexVec<_, _> =
-            mir.predecessors().iter().map(|ps| ps.len()).collect();
+        add_call_guards(mir);
+    }
+}
+
+pub fn add_call_guards(mir: &mut Mir) {
+    let pred_count: IndexVec<_, _> =
+        mir.predecessors().iter().map(|ps| ps.len()).collect();
 
-        // We need a place to store the new blocks generated
-        let mut new_blocks = Vec::new();
+    // We need a place to store the new blocks generated
+    let mut new_blocks = Vec::new();
 
-        let cur_len = mir.basic_blocks().len();
+    let cur_len = mir.basic_blocks().len();
 
-        for block in mir.basic_blocks_mut() {
-            match block.terminator {
-                Some(Terminator {
-                    kind: TerminatorKind::Call {
-                        destination: Some((_, ref mut destination)),
-                        cleanup: Some(_),
-                        ..
-                    }, source_info
-                }) if pred_count[*destination] > 1 => {
-                    // It's a critical edge, break it
-                    let call_guard = BasicBlockData {
-                        statements: vec![],
-                        is_cleanup: block.is_cleanup,
-                        terminator: Some(Terminator {
-                            source_info: source_info,
-                            kind: TerminatorKind::Goto { target: *destination }
-                        })
-                    };
+    for block in mir.basic_blocks_mut() {
+        match block.terminator {
+            Some(Terminator {
+                kind: TerminatorKind::Call {
+                    destination: Some((_, ref mut destination)),
+                    cleanup: Some(_),
+                    ..
+                }, source_info
+            }) if pred_count[*destination] > 1 => {
+                // It's a critical edge, break it
+                let call_guard = BasicBlockData {
+                    statements: vec![],
+                    is_cleanup: block.is_cleanup,
+                    terminator: Some(Terminator {
+                        source_info: source_info,
+                        kind: TerminatorKind::Goto { target: *destination }
+                    })
+                };
 
-                    // Get the index it will be when inserted into the MIR
-                    let idx = cur_len + new_blocks.len();
-                    new_blocks.push(call_guard);
-                    *destination = BasicBlock::new(idx);
-                }
-                _ => {}
+                // Get the index it will be when inserted into the MIR
+                let idx = cur_len + new_blocks.len();
+                new_blocks.push(call_guard);
+                *destination = BasicBlock::new(idx);
             }
+            _ => {}
         }
+    }
 
-        debug!("Broke {} N edges", new_blocks.len());
+    debug!("Broke {} N edges", new_blocks.len());
 
-        mir.basic_blocks_mut().extend(new_blocks);
-    }
+    mir.basic_blocks_mut().extend(new_blocks);
 }
 
 impl Pass for AddCallGuards {}
index 2194c20c2f442fe3e62dff7771f6c5623c4fb3b7..5d127a5aed4618d0c5c76e8380f2eb744e346120 100644 (file)
 //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
 //! future.
 
-use def_use::DefUseAnalysis;
 use rustc::mir::{Constant, Local, LocalKind, Location, Lvalue, Mir, Operand, Rvalue, StatementKind};
 use rustc::mir::transform::{MirPass, MirSource, Pass};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
+use util::def_use::DefUseAnalysis;
 use transform::qualify_consts;
 
 pub struct CopyPropagation;
index 035f33de91aa5d15dca3bcc9048046bc5d20918c..f22a71636a98e883028c090f294e964be3dea271 100644 (file)
@@ -15,7 +15,7 @@
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
 use rustc::mir::transform::{Pass, MirPass, MirPassHook, MirSource};
-use pretty;
+use util as mir_util;
 
 pub struct Marker<'a>(pub &'a str);
 
@@ -56,7 +56,7 @@ fn on_mir_pass<'a>(
         pass: &Pass,
         is_after: bool)
     {
-        pretty::dump_mir(
+        mir_util::dump_mir(
             tcx,
             &*pass.name(),
             &Disambiguator {
index 55a26f4b37fe2521ae208ecee36cf8e0ec02aa49..3654ae6940c5257b11cf9ae37ed81d8f430b159a 100644 (file)
@@ -42,12 +42,16 @@ fn visit_terminator(&mut self,
     }
 }
 
+pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) {
+    if tcx.sess.no_landing_pads() {
+        NoLandingPads.visit_mir(mir);
+    }
+}
+
 impl<'tcx> MirPass<'tcx> for NoLandingPads {
     fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     _: MirSource, mir: &mut Mir<'tcx>) {
-        if tcx.sess.no_landing_pads() {
-            self.visit_mir(mir);
-        }
+        no_landing_pads(tcx, mir)
     }
 }
 
index a762507f35e7ecccdaf994db4667df34048b5266..0a8f147b2141055ac0cec37a56a0e5659bbd421d 100644 (file)
@@ -53,14 +53,18 @@ pub fn new(label: &'a str) -> Self {
     }
 }
 
+pub fn simplify_cfg(mir: &mut Mir) {
+    CfgSimplifier::new(mir).simplify();
+    remove_dead_blocks(mir);
+
+    // FIXME: Should probably be moved into some kind of pass manager
+    mir.basic_blocks_mut().raw.shrink_to_fit();
+}
+
 impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
     fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
         debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
-        CfgSimplifier::new(mir).simplify();
-        remove_dead_blocks(mir);
-
-        // FIXME: Should probably be moved into some kind of pass manager
-        mir.basic_blocks_mut().raw.shrink_to_fit();
+        simplify_cfg(mir);
     }
 }
 
diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs
new file mode 100644 (file)
index 0000000..d20d50c
--- /dev/null
@@ -0,0 +1,163 @@
+// 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.
+
+//! Def-use analysis.
+
+use rustc::mir::{Local, Location, Lvalue, Mir};
+use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor};
+use rustc_data_structures::indexed_vec::IndexVec;
+use std::marker::PhantomData;
+use std::mem;
+
+pub struct DefUseAnalysis<'tcx> {
+    info: IndexVec<Local, Info<'tcx>>,
+}
+
+#[derive(Clone)]
+pub struct Info<'tcx> {
+    pub defs_and_uses: Vec<Use<'tcx>>,
+}
+
+#[derive(Clone)]
+pub struct Use<'tcx> {
+    pub context: LvalueContext<'tcx>,
+    pub location: Location,
+}
+
+impl<'tcx> DefUseAnalysis<'tcx> {
+    pub fn new(mir: &Mir<'tcx>) -> DefUseAnalysis<'tcx> {
+        DefUseAnalysis {
+            info: IndexVec::from_elem_n(Info::new(), mir.local_decls.len()),
+        }
+    }
+
+    pub fn analyze(&mut self, mir: &Mir<'tcx>) {
+        let mut finder = DefUseFinder {
+            info: mem::replace(&mut self.info, IndexVec::new()),
+        };
+        finder.visit_mir(mir);
+        self.info = finder.info
+    }
+
+    pub fn local_info(&self, local: Local) -> &Info<'tcx> {
+        &self.info[local]
+    }
+
+    pub fn local_info_mut(&mut self, local: Local) -> &mut Info<'tcx> {
+        &mut self.info[local]
+    }
+
+    fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'tcx>, mut callback: F)
+                               where F: for<'a> FnMut(&'a mut Lvalue<'tcx>,
+                                                      LvalueContext<'tcx>,
+                                                      Location) {
+        for lvalue_use in &self.info[local].defs_and_uses {
+            MutateUseVisitor::new(local,
+                                  &mut callback,
+                                  mir).visit_location(mir, lvalue_use.location)
+        }
+    }
+
+    /// FIXME(pcwalton): This should update the def-use chains.
+    pub fn replace_all_defs_and_uses_with(&self,
+                                          local: Local,
+                                          mir: &mut Mir<'tcx>,
+                                          new_lvalue: Lvalue<'tcx>) {
+        self.mutate_defs_and_uses(local, mir, |lvalue, _, _| *lvalue = new_lvalue.clone())
+    }
+}
+
+struct DefUseFinder<'tcx> {
+    info: IndexVec<Local, Info<'tcx>>,
+}
+
+impl<'tcx> DefUseFinder<'tcx> {
+    fn lvalue_mut_info(&mut self, lvalue: &Lvalue<'tcx>) -> Option<&mut Info<'tcx>> {
+        let info = &mut self.info;
+
+        if let Lvalue::Local(local) = *lvalue {
+            Some(&mut info[local])
+        } else {
+            None
+        }
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for DefUseFinder<'tcx> {
+    fn visit_lvalue(&mut self,
+                    lvalue: &Lvalue<'tcx>,
+                    context: LvalueContext<'tcx>,
+                    location: Location) {
+        if let Some(ref mut info) = self.lvalue_mut_info(lvalue) {
+            info.defs_and_uses.push(Use {
+                context: context,
+                location: location,
+            })
+        }
+        self.super_lvalue(lvalue, context, location)
+    }
+}
+
+impl<'tcx> Info<'tcx> {
+    fn new() -> Info<'tcx> {
+        Info {
+            defs_and_uses: vec![],
+        }
+    }
+
+    pub fn def_count(&self) -> usize {
+        self.defs_and_uses.iter().filter(|lvalue_use| lvalue_use.context.is_mutating_use()).count()
+    }
+
+    pub fn def_count_not_including_drop(&self) -> usize {
+        self.defs_and_uses.iter().filter(|lvalue_use| {
+            lvalue_use.context.is_mutating_use() && !lvalue_use.context.is_drop()
+        }).count()
+    }
+
+    pub fn use_count(&self) -> usize {
+        self.defs_and_uses.iter().filter(|lvalue_use| {
+            lvalue_use.context.is_nonmutating_use()
+        }).count()
+    }
+}
+
+struct MutateUseVisitor<'tcx, F> {
+    query: Local,
+    callback: F,
+    phantom: PhantomData<&'tcx ()>,
+}
+
+impl<'tcx, F> MutateUseVisitor<'tcx, F> {
+    fn new(query: Local, callback: F, _: &Mir<'tcx>)
+           -> MutateUseVisitor<'tcx, F>
+           where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) {
+        MutateUseVisitor {
+            query: query,
+            callback: callback,
+            phantom: PhantomData,
+        }
+    }
+}
+
+impl<'tcx, F> MutVisitor<'tcx> for MutateUseVisitor<'tcx, F>
+              where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) {
+    fn visit_lvalue(&mut self,
+                    lvalue: &mut Lvalue<'tcx>,
+                    context: LvalueContext<'tcx>,
+                    location: Location) {
+        if let Lvalue::Local(local) = *lvalue {
+            if local == self.query {
+                (self.callback)(lvalue, context, location)
+            }
+        }
+        self.super_lvalue(lvalue, context, location)
+    }
+}
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
new file mode 100644 (file)
index 0000000..d0f142a
--- /dev/null
@@ -0,0 +1,696 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+use rustc::hir;
+use rustc::mir::*;
+use rustc::middle::const_val::ConstInt;
+use rustc::middle::lang_items;
+use rustc::ty::{self, Ty};
+use rustc::ty::subst::{Kind, Substs};
+use rustc::ty::util::IntTypeExt;
+use rustc_data_structures::indexed_vec::Idx;
+use util::patch::MirPatch;
+
+use std::iter;
+
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+pub enum DropFlagState {
+    Present, // i.e. initialized
+    Absent, // i.e. deinitialized or "moved"
+}
+
+impl DropFlagState {
+    pub fn value(self) -> bool {
+        match self {
+            DropFlagState::Present => true,
+            DropFlagState::Absent => false
+        }
+    }
+}
+
+#[derive(Debug)]
+pub enum DropStyle {
+    Dead,
+    Static,
+    Conditional,
+    Open,
+}
+
+#[derive(Debug)]
+pub enum DropFlagMode {
+    Shallow,
+    Deep
+}
+
+pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
+    type Path : Copy + fmt::Debug;
+
+    fn patch(&mut self) -> &mut MirPatch<'tcx>;
+    fn mir(&self) -> &'a Mir<'tcx>;
+    fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx>;
+    fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx>;
+
+    fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle;
+    fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>>;
+    fn clear_drop_flag(&mut self, location: Location, path: Self::Path, mode: DropFlagMode);
+
+
+    fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path>;
+    fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path>;
+    fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path>;
+}
+
+#[derive(Debug)]
+struct DropCtxt<'l, 'b: 'l, 'tcx: 'b, D>
+    where D : DropElaborator<'b, 'tcx> + 'l
+{
+    elaborator: &'l mut D,
+
+    source_info: SourceInfo,
+    is_cleanup: bool,
+
+    lvalue: &'l Lvalue<'tcx>,
+    path: D::Path,
+    succ: BasicBlock,
+    unwind: Option<BasicBlock>,
+}
+
+pub fn elaborate_drop<'b, 'tcx, D>(
+    elaborator: &mut D,
+    source_info: SourceInfo,
+    is_cleanup: bool,
+    lvalue: &Lvalue<'tcx>,
+    path: D::Path,
+    succ: BasicBlock,
+    unwind: Option<BasicBlock>,
+    bb: BasicBlock)
+    where D: DropElaborator<'b, 'tcx>
+{
+    assert_eq!(unwind.is_none(), is_cleanup);
+    DropCtxt {
+        elaborator, source_info, is_cleanup, lvalue, path, succ, unwind
+    }.elaborate_drop(bb)
+}
+
+impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
+    where D: DropElaborator<'b, 'tcx>
+{
+    fn lvalue_ty(&self, lvalue: &Lvalue<'tcx>) -> Ty<'tcx> {
+        lvalue.ty(self.elaborator.mir(), self.tcx()).to_ty(self.tcx())
+    }
+
+    fn tcx(&self) -> ty::TyCtxt<'b, 'tcx, 'tcx> {
+        self.elaborator.tcx()
+    }
+
+    /// This elaborates a single drop instruction, located at `bb`, and
+    /// patches over it.
+    ///
+    /// The elaborated drop checks the drop flags to only drop what
+    /// is initialized.
+    ///
+    /// In addition, the relevant drop flags also need to be cleared
+    /// to avoid double-drops. However, in the middle of a complex
+    /// drop, one must avoid clearing some of the flags before they
+    /// are read, as that would cause a memory leak.
+    ///
+    /// In particular, when dropping an ADT, multiple fields may be
+    /// joined together under the `rest` subpath. They are all controlled
+    /// by the primary drop flag, but only the last rest-field dropped
+    /// should clear it (and it must also not clear anything else).
+    ///
+    /// FIXME: I think we should just control the flags externally
+    /// and then we do not need this machinery.
+    pub fn elaborate_drop<'a>(&mut self, bb: BasicBlock) {
+        debug!("elaborate_drop({:?})", self);
+        let style = self.elaborator.drop_style(self.path, DropFlagMode::Deep);
+        debug!("elaborate_drop({:?}): live - {:?}", self, style);
+        match style {
+            DropStyle::Dead => {
+                self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto {
+                    target: self.succ
+                });
+            }
+            DropStyle::Static => {
+                let loc = self.terminator_loc(bb);
+                self.elaborator.clear_drop_flag(loc, self.path, DropFlagMode::Deep);
+                self.elaborator.patch().patch_terminator(bb, TerminatorKind::Drop {
+                    location: self.lvalue.clone(),
+                    target: self.succ,
+                    unwind: self.unwind
+                });
+            }
+            DropStyle::Conditional => {
+                let is_cleanup = self.is_cleanup; // FIXME(#6393)
+                let succ = self.succ;
+                let drop_bb = self.complete_drop(
+                    is_cleanup, Some(DropFlagMode::Deep), succ);
+                self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto {
+                    target: drop_bb
+                });
+            }
+            DropStyle::Open => {
+                let drop_bb = self.open_drop();
+                self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto {
+                    target: drop_bb
+                });
+            }
+        }
+    }
+
+    /// Return the lvalue and move path for each field of `variant`,
+    /// (the move path is `None` if the field is a rest field).
+    fn move_paths_for_fields(&self,
+                             base_lv: &Lvalue<'tcx>,
+                             variant_path: D::Path,
+                             variant: &'tcx ty::VariantDef,
+                             substs: &'tcx Substs<'tcx>)
+                             -> Vec<(Lvalue<'tcx>, Option<D::Path>)>
+    {
+        variant.fields.iter().enumerate().map(|(i, f)| {
+            let field = Field::new(i);
+            let subpath = self.elaborator.field_subpath(variant_path, field);
+
+            let field_ty =
+                self.tcx().normalize_associated_type_in_env(
+                    &f.ty(self.tcx(), substs),
+                    self.elaborator.param_env()
+                );
+            (base_lv.clone().field(field, field_ty), subpath)
+        }).collect()
+    }
+
+    fn drop_subpath(&mut self,
+                    is_cleanup: bool,
+                    lvalue: &Lvalue<'tcx>,
+                    path: Option<D::Path>,
+                    succ: BasicBlock,
+                    unwind: Option<BasicBlock>)
+                    -> BasicBlock
+    {
+        if let Some(path) = path {
+            debug!("drop_subpath: for std field {:?}", lvalue);
+
+            DropCtxt {
+                elaborator: self.elaborator,
+                source_info: self.source_info,
+                path, lvalue, succ, unwind, is_cleanup
+            }.elaborated_drop_block()
+        } else {
+            debug!("drop_subpath: for rest field {:?}", lvalue);
+
+            DropCtxt {
+                elaborator: self.elaborator,
+                source_info: self.source_info,
+                lvalue, succ, unwind, is_cleanup,
+                // Using `self.path` here to condition the drop on
+                // our own drop flag.
+                path: self.path
+            }.complete_drop(is_cleanup, None, succ)
+        }
+    }
+
+    /// Create one-half of the drop ladder for a list of fields, and return
+    /// the list of steps in it in reverse order.
+    ///
+    /// `unwind_ladder` is such a list of steps in reverse order,
+    /// which is called instead of the next step if the drop unwinds
+    /// (the first field is never reached). If it is `None`, all
+    /// unwind targets are left blank.
+    fn drop_halfladder<'a>(&mut self,
+                           unwind_ladder: Option<&[BasicBlock]>,
+                           succ: BasicBlock,
+                           fields: &[(Lvalue<'tcx>, Option<D::Path>)],
+                           is_cleanup: bool)
+                           -> Vec<BasicBlock>
+    {
+        let mut unwind_succ = if is_cleanup {
+            None
+        } else {
+            self.unwind
+        };
+
+        let goto = TerminatorKind::Goto { target: succ };
+        let mut succ = self.new_block(is_cleanup, goto);
+
+        // Always clear the "master" drop flag at the bottom of the
+        // ladder. This is needed because the "master" drop flag
+        // protects the ADT's discriminant, which is invalidated
+        // after the ADT is dropped.
+        let succ_loc = Location { block: succ, statement_index: 0 };
+        self.elaborator.clear_drop_flag(succ_loc, self.path, DropFlagMode::Shallow);
+
+        fields.iter().rev().enumerate().map(|(i, &(ref lv, path))| {
+            succ = self.drop_subpath(is_cleanup, lv, path, succ, unwind_succ);
+            unwind_succ = unwind_ladder.as_ref().map(|p| p[i]);
+            succ
+        }).collect()
+    }
+
+    /// Create a full drop ladder, consisting of 2 connected half-drop-ladders
+    ///
+    /// For example, with 3 fields, the drop ladder is
+    ///
+    /// .d0:
+    ///     ELAB(drop location.0 [target=.d1, unwind=.c1])
+    /// .d1:
+    ///     ELAB(drop location.1 [target=.d2, unwind=.c2])
+    /// .d2:
+    ///     ELAB(drop location.2 [target=`self.succ`, unwind=`self.unwind`])
+    /// .c1:
+    ///     ELAB(drop location.1 [target=.c2])
+    /// .c2:
+    ///     ELAB(drop location.2 [target=`self.unwind`])
+    fn drop_ladder<'a>(&mut self,
+                       fields: Vec<(Lvalue<'tcx>, Option<D::Path>)>)
+                       -> (BasicBlock, Option<BasicBlock>)
+    {
+        debug!("drop_ladder({:?}, {:?})", self, fields);
+
+        let mut fields = fields;
+        fields.retain(|&(ref lvalue, _)| {
+            self.tcx().type_needs_drop_given_env(
+                self.lvalue_ty(lvalue), self.elaborator.param_env())
+        });
+
+        debug!("drop_ladder - fields needing drop: {:?}", fields);
+
+        let unwind_ladder = if self.is_cleanup {
+            None
+        } else {
+            let unwind = self.unwind.unwrap(); // FIXME(#6393)
+            Some(self.drop_halfladder(None, unwind, &fields, true))
+        };
+
+        let succ = self.succ; // FIXME(#6393)
+        let is_cleanup = self.is_cleanup;
+        let normal_ladder =
+            self.drop_halfladder(unwind_ladder.as_ref().map(|x| &**x),
+                                 succ, &fields, is_cleanup);
+
+        (normal_ladder.last().cloned().unwrap_or(succ),
+         unwind_ladder.and_then(|l| l.last().cloned()).or(self.unwind))
+    }
+
+    fn open_drop_for_tuple<'a>(&mut self, tys: &[Ty<'tcx>])
+                               -> BasicBlock
+    {
+        debug!("open_drop_for_tuple({:?}, {:?})", self, tys);
+
+        let fields = tys.iter().enumerate().map(|(i, &ty)| {
+            (self.lvalue.clone().field(Field::new(i), ty),
+             self.elaborator.field_subpath(self.path, Field::new(i)))
+        }).collect();
+
+        self.drop_ladder(fields).0
+    }
+
+    fn open_drop_for_box<'a>(&mut self, ty: Ty<'tcx>) -> BasicBlock
+    {
+        debug!("open_drop_for_box({:?}, {:?})", self, ty);
+
+        let interior = self.lvalue.clone().deref();
+        let interior_path = self.elaborator.deref_subpath(self.path);
+
+        let succ = self.succ; // FIXME(#6393)
+        let is_cleanup = self.is_cleanup;
+        let succ = self.box_free_block(ty, succ, is_cleanup);
+        let unwind_succ = self.unwind.map(|u| {
+            self.box_free_block(ty, u, true)
+        });
+
+        self.drop_subpath(is_cleanup, &interior, interior_path, succ, unwind_succ)
+    }
+
+    fn open_drop_for_adt<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>)
+                             -> BasicBlock {
+        debug!("open_drop_for_adt({:?}, {:?}, {:?})", self, adt, substs);
+        if adt.variants.len() == 0 {
+            return self.elaborator.patch().new_block(BasicBlockData {
+                statements: vec![],
+                terminator: Some(Terminator {
+                    source_info: self.source_info,
+                    kind: TerminatorKind::Unreachable
+                }),
+                is_cleanup: self.is_cleanup
+            });
+        }
+
+        let contents_drop = if adt.is_union() {
+            (self.succ, self.unwind)
+        } else {
+            self.open_drop_for_adt_contents(adt, substs)
+        };
+
+        if adt.has_dtor(self.tcx()) {
+            self.destructor_call_block(contents_drop)
+        } else {
+            contents_drop.0
+        }
+    }
+
+    fn open_drop_for_adt_contents<'a>(&mut self, adt: &'tcx ty::AdtDef,
+                                      substs: &'tcx Substs<'tcx>)
+                                      -> (BasicBlock, Option<BasicBlock>) {
+        match adt.variants.len() {
+            1 => {
+                let fields = self.move_paths_for_fields(
+                    self.lvalue,
+                    self.path,
+                    &adt.variants[0],
+                    substs
+                );
+                self.drop_ladder(fields)
+            }
+            _ => {
+                let is_cleanup = self.is_cleanup;
+                let succ = self.succ;
+                let unwind = self.unwind; // FIXME(#6393)
+
+                let mut values = Vec::with_capacity(adt.variants.len());
+                let mut normal_blocks = Vec::with_capacity(adt.variants.len());
+                let mut unwind_blocks = if is_cleanup {
+                    None
+                } else {
+                    Some(Vec::with_capacity(adt.variants.len()))
+                };
+                let mut otherwise = None;
+                let mut unwind_otherwise = None;
+                for (variant_index, discr) in adt.discriminants(self.tcx()).enumerate() {
+                    let subpath = self.elaborator.downcast_subpath(
+                        self.path, variant_index);
+                    if let Some(variant_path) = subpath {
+                        let base_lv = self.lvalue.clone().elem(
+                            ProjectionElem::Downcast(adt, variant_index)
+                        );
+                        let fields = self.move_paths_for_fields(
+                            &base_lv,
+                            variant_path,
+                            &adt.variants[variant_index],
+                            substs);
+                        values.push(discr);
+                        if let Some(ref mut unwind_blocks) = unwind_blocks {
+                            // We can't use the half-ladder from the original
+                            // drop ladder, because this breaks the
+                            // "funclet can't have 2 successor funclets"
+                            // requirement from MSVC:
+                            //
+                            //           switch       unwind-switch
+                            //          /      \         /        \
+                            //         v1.0    v2.0  v2.0-unwind  v1.0-unwind
+                            //         |        |      /             |
+                            //    v1.1-unwind  v2.1-unwind           |
+                            //      ^                                |
+                            //       \-------------------------------/
+                            //
+                            // Create a duplicate half-ladder to avoid that. We
+                            // could technically only do this on MSVC, but I
+                            // I want to minimize the divergence between MSVC
+                            // and non-MSVC.
+
+                            let unwind = unwind.unwrap();
+                            let halfladder = self.drop_halfladder(
+                                None, unwind, &fields, true);
+                            unwind_blocks.push(
+                                halfladder.last().cloned().unwrap_or(unwind)
+                            );
+                        }
+                        let (normal, _) = self.drop_ladder(fields);
+                        normal_blocks.push(normal);
+                    } else {
+                        // variant not found - drop the entire enum
+                        if let None = otherwise {
+                            otherwise = Some(self.complete_drop(
+                                is_cleanup,
+                                Some(DropFlagMode::Shallow),
+                                succ));
+                            unwind_otherwise = unwind.map(|unwind| self.complete_drop(
+                                true,
+                                Some(DropFlagMode::Shallow),
+                                unwind
+                            ));
+                        }
+                    }
+                }
+                if let Some(block) = otherwise {
+                    normal_blocks.push(block);
+                    if let Some(ref mut unwind_blocks) = unwind_blocks {
+                        unwind_blocks.push(unwind_otherwise.unwrap());
+                    }
+                } else {
+                    values.pop();
+                }
+
+                (self.adt_switch_block(is_cleanup, adt, normal_blocks, &values, succ),
+                 unwind_blocks.map(|unwind_blocks| {
+                     self.adt_switch_block(
+                         is_cleanup, adt, unwind_blocks, &values, unwind.unwrap()
+                     )
+                 }))
+            }
+        }
+    }
+
+    fn adt_switch_block(&mut self,
+                        is_cleanup: bool,
+                        adt: &'tcx ty::AdtDef,
+                        blocks: Vec<BasicBlock>,
+                        values: &[ConstInt],
+                        succ: BasicBlock)
+                        -> BasicBlock {
+        // If there are multiple variants, then if something
+        // is present within the enum the discriminant, tracked
+        // by the rest path, must be initialized.
+        //
+        // Additionally, we do not want to switch on the
+        // discriminant after it is free-ed, because that
+        // way lies only trouble.
+        let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
+        let discr = Lvalue::Local(self.new_temp(discr_ty));
+        let discr_rv = Rvalue::Discriminant(self.lvalue.clone());
+        let switch_block = self.elaborator.patch().new_block(BasicBlockData {
+            statements: vec![
+                Statement {
+                    source_info: self.source_info,
+                    kind: StatementKind::Assign(discr.clone(), discr_rv),
+                }
+                ],
+            terminator: Some(Terminator {
+                source_info: self.source_info,
+                kind: TerminatorKind::SwitchInt {
+                    discr: Operand::Consume(discr),
+                    switch_ty: discr_ty,
+                    values: From::from(values.to_owned()),
+                    targets: blocks,
+                }
+            }),
+            is_cleanup: is_cleanup,
+        });
+        self.drop_flag_test_block(is_cleanup, switch_block, succ)
+    }
+
+    fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Option<BasicBlock>))
+                                 -> BasicBlock
+    {
+        debug!("destructor_call_block({:?}, {:?})", self, succ);
+        let tcx = self.tcx();
+        let drop_trait = tcx.lang_items.drop_trait().unwrap();
+        let drop_fn = tcx.associated_items(drop_trait).next().unwrap();
+        let ty = self.lvalue_ty(self.lvalue);
+        let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
+
+        let re_erased = tcx.mk_region(ty::ReErased);
+        let ref_ty = tcx.mk_ref(re_erased, ty::TypeAndMut {
+            ty: ty,
+            mutbl: hir::Mutability::MutMutable
+        });
+        let ref_lvalue = self.new_temp(ref_ty);
+        let unit_temp = Lvalue::Local(self.new_temp(tcx.mk_nil()));
+
+        self.elaborator.patch().new_block(BasicBlockData {
+            statements: vec![Statement {
+                source_info: self.source_info,
+                kind: StatementKind::Assign(
+                    Lvalue::Local(ref_lvalue),
+                    Rvalue::Ref(re_erased, BorrowKind::Mut, self.lvalue.clone())
+                )
+            }],
+            terminator: Some(Terminator {
+                kind: TerminatorKind::Call {
+                    func: Operand::item(tcx, drop_fn.def_id, substs,
+                                        self.source_info.span),
+                    args: vec![Operand::Consume(Lvalue::Local(ref_lvalue))],
+                    destination: Some((unit_temp, succ)),
+                    cleanup: unwind,
+                },
+                source_info: self.source_info
+            }),
+            is_cleanup: self.is_cleanup,
+        })
+    }
+
+    /// The slow-path - create an "open", elaborated drop for a type
+    /// which is moved-out-of only partially, and patch `bb` to a jump
+    /// to it. This must not be called on ADTs with a destructor,
+    /// as these can't be moved-out-of, except for `Box<T>`, which is
+    /// special-cased.
+    ///
+    /// This creates a "drop ladder" that drops the needed fields of the
+    /// ADT, both in the success case or if one of the destructors fail.
+    fn open_drop<'a>(&mut self) -> BasicBlock {
+        let ty = self.lvalue_ty(self.lvalue);
+        let is_cleanup = self.is_cleanup; // FIXME(#6393)
+        let succ = self.succ;
+        match ty.sty {
+            ty::TyClosure(def_id, substs) => {
+                let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
+                self.open_drop_for_tuple(&tys)
+            }
+            ty::TyTuple(tys, _) => {
+                self.open_drop_for_tuple(tys)
+            }
+            ty::TyAdt(def, _) if def.is_box() => {
+                self.open_drop_for_box(ty.boxed_ty())
+            }
+            ty::TyAdt(def, substs) => {
+                self.open_drop_for_adt(def, substs)
+            }
+            ty::TyDynamic(..) => {
+                self.complete_drop(is_cleanup, Some(DropFlagMode::Deep), succ)
+            }
+            ty::TyArray(..) | ty::TySlice(..) => {
+                // FIXME(#34708): handle partially-dropped
+                // array/slice elements.
+                self.complete_drop(is_cleanup, Some(DropFlagMode::Deep), succ)
+            }
+            _ => bug!("open drop from non-ADT `{:?}`", ty)
+        }
+    }
+
+    /// Return a basic block that drop an lvalue using the context
+    /// and path in `c`. If `mode` is something, also clear `c`
+    /// according to it.
+    ///
+    /// if FLAG(self.path)
+    ///     if let Some(mode) = mode: FLAG(self.path)[mode] = false
+    ///     drop(self.lv)
+    fn complete_drop<'a>(&mut self,
+                         is_cleanup: bool,
+                         drop_mode: Option<DropFlagMode>,
+                         succ: BasicBlock) -> BasicBlock
+    {
+        debug!("complete_drop({:?},{:?})", self, drop_mode);
+
+        let drop_block = self.drop_block(is_cleanup, succ);
+        if let Some(mode) = drop_mode {
+            let block_start = Location { block: drop_block, statement_index: 0 };
+            self.elaborator.clear_drop_flag(block_start, self.path, mode);
+        }
+
+        self.drop_flag_test_block(is_cleanup, drop_block, succ)
+    }
+
+    fn elaborated_drop_block<'a>(&mut self) -> BasicBlock {
+        debug!("elaborated_drop_block({:?})", self);
+        let is_cleanup = self.is_cleanup; // FIXME(#6393)
+        let succ = self.succ;
+        let blk = self.drop_block(is_cleanup, succ);
+        self.elaborate_drop(blk);
+        blk
+    }
+
+    fn box_free_block<'a>(
+        &mut self,
+        ty: Ty<'tcx>,
+        target: BasicBlock,
+        is_cleanup: bool
+    ) -> BasicBlock {
+        let block = self.unelaborated_free_block(ty, target, is_cleanup);
+        self.drop_flag_test_block(is_cleanup, block, target)
+    }
+
+    fn unelaborated_free_block<'a>(
+        &mut self,
+        ty: Ty<'tcx>,
+        target: BasicBlock,
+        is_cleanup: bool
+    ) -> BasicBlock {
+        let tcx = self.tcx();
+        let unit_temp = Lvalue::Local(self.new_temp(tcx.mk_nil()));
+        let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
+        let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
+
+        let call = TerminatorKind::Call {
+            func: Operand::item(tcx, free_func, substs, self.source_info.span),
+            args: vec![Operand::Consume(self.lvalue.clone())],
+            destination: Some((unit_temp, target)),
+            cleanup: None
+        }; // FIXME(#6393)
+        let free_block = self.new_block(is_cleanup, call);
+
+        let block_start = Location { block: free_block, statement_index: 0 };
+        self.elaborator.clear_drop_flag(block_start, self.path, DropFlagMode::Shallow);
+        free_block
+    }
+
+    fn drop_block<'a>(&mut self, is_cleanup: bool, succ: BasicBlock) -> BasicBlock {
+        let block = TerminatorKind::Drop {
+            location: self.lvalue.clone(),
+            target: succ,
+            unwind: if is_cleanup { None } else { self.unwind }
+        };
+        self.new_block(is_cleanup, block)
+    }
+
+    fn drop_flag_test_block(&mut self,
+                            is_cleanup: bool,
+                            on_set: BasicBlock,
+                            on_unset: BasicBlock)
+                            -> BasicBlock
+    {
+        let style = self.elaborator.drop_style(self.path, DropFlagMode::Shallow);
+        debug!("drop_flag_test_block({:?},{:?},{:?}) - {:?}",
+               self, is_cleanup, on_set, style);
+
+        match style {
+            DropStyle::Dead => on_unset,
+            DropStyle::Static => on_set,
+            DropStyle::Conditional | DropStyle::Open => {
+                let flag = self.elaborator.get_drop_flag(self.path).unwrap();
+                let term = TerminatorKind::if_(self.tcx(), flag, on_set, on_unset);
+                self.new_block(is_cleanup, term)
+            }
+        }
+    }
+
+    fn new_block<'a>(&mut self,
+                     is_cleanup: bool,
+                     k: TerminatorKind<'tcx>)
+                     -> BasicBlock
+    {
+        self.elaborator.patch().new_block(BasicBlockData {
+            statements: vec![],
+            terminator: Some(Terminator {
+                source_info: self.source_info, kind: k
+            }),
+            is_cleanup: is_cleanup
+        })
+    }
+
+    fn new_temp(&mut self, ty: Ty<'tcx>) -> Local {
+        self.elaborator.patch().new_temp(ty)
+    }
+
+    fn terminator_loc(&mut self, bb: BasicBlock) -> Location {
+        let mir = self.elaborator.mir();
+        self.elaborator.patch().terminator_loc(mir, bb)
+    }
+}
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
new file mode 100644 (file)
index 0000000..91600b9
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use dot;
+use rustc::hir::def_id::DefId;
+use rustc::mir::*;
+use rustc::ty::TyCtxt;
+use std::fmt::Debug;
+use std::io::{self, Write};
+use syntax::ast::NodeId;
+
+use rustc_data_structures::indexed_vec::Idx;
+
+/// Write a graphviz DOT graph of a list of MIRs.
+pub fn write_mir_graphviz<'a, 'b, 'tcx, W, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
+                                              iter: I,
+                                              w: &mut W)
+                                              -> io::Result<()>
+    where W: Write, I: Iterator<Item=DefId>
+{
+    for def_id in iter {
+        let nodeid = tcx.hir.as_local_node_id(def_id).unwrap();
+        let mir = &tcx.item_mir(def_id);
+
+        writeln!(w, "digraph Mir_{} {{", nodeid)?;
+
+        // Global graph properties
+        writeln!(w, r#"    graph [fontname="monospace"];"#)?;
+        writeln!(w, r#"    node [fontname="monospace"];"#)?;
+        writeln!(w, r#"    edge [fontname="monospace"];"#)?;
+
+        // Graph label
+        write_graph_label(tcx, nodeid, mir, w)?;
+
+        // Nodes
+        for (block, _) in mir.basic_blocks().iter_enumerated() {
+            write_node(block, mir, w)?;
+        }
+
+        // Edges
+        for (source, _) in mir.basic_blocks().iter_enumerated() {
+            write_edges(source, mir, w)?;
+        }
+        writeln!(w, "}}")?
+    }
+    Ok(())
+}
+
+/// Write a graphviz HTML-styled label for the given basic block, with
+/// all necessary escaping already performed. (This is suitable for
+/// emitting directly, as is done in this module, or for use with the
+/// LabelText::HtmlStr from libgraphviz.)
+///
+/// `init` and `fini` are callbacks for emitting additional rows of
+/// data (using HTML enclosed with `<tr>` in the emitted text).
+pub fn write_node_label<W: Write, INIT, FINI>(block: BasicBlock,
+                                              mir: &Mir,
+                                              w: &mut W,
+                                              num_cols: u32,
+                                              init: INIT,
+                                              fini: FINI) -> io::Result<()>
+    where INIT: Fn(&mut W) -> io::Result<()>,
+          FINI: Fn(&mut W) -> io::Result<()>
+{
+    let data = &mir[block];
+
+    write!(w, r#"<table border="0" cellborder="1" cellspacing="0">"#)?;
+
+    // Basic block number at the top.
+    write!(w, r#"<tr><td {attrs} colspan="{colspan}">{blk}</td></tr>"#,
+           attrs=r#"bgcolor="gray" align="center""#,
+           colspan=num_cols,
+           blk=block.index())?;
+
+    init(w)?;
+
+    // List of statements in the middle.
+    if !data.statements.is_empty() {
+        write!(w, r#"<tr><td align="left" balign="left">"#)?;
+        for statement in &data.statements {
+            write!(w, "{}<br/>", escape(statement))?;
+        }
+        write!(w, "</td></tr>")?;
+    }
+
+    // Terminator head at the bottom, not including the list of successor blocks. Those will be
+    // displayed as labels on the edges between blocks.
+    let mut terminator_head = String::new();
+    data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
+    write!(w, r#"<tr><td align="left">{}</td></tr>"#, dot::escape_html(&terminator_head))?;
+
+    fini(w)?;
+
+    // Close the table
+    writeln!(w, "</table>")
+}
+
+/// Write a graphviz DOT node for the given basic block.
+fn write_node<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
+    // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
+    write!(w, r#"    {} [shape="none", label=<"#, node(block))?;
+    write_node_label(block, mir, w, 1, |_| Ok(()), |_| Ok(()))?;
+    // Close the node label and the node itself.
+    writeln!(w, ">];")
+}
+
+/// Write graphviz DOT edges with labels between the given basic block and all of its successors.
+fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
+    let terminator = mir[source].terminator();
+    let labels = terminator.kind.fmt_successor_labels();
+
+    for (&target, label) in terminator.successors().iter().zip(labels) {
+        writeln!(w, r#"    {} -> {} [label="{}"];"#, node(source), node(target), label)?;
+    }
+
+    Ok(())
+}
+
+/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
+/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
+/// all the variables and temporaries.
+fn write_graph_label<'a, 'tcx, W: Write>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                         nid: NodeId,
+                                         mir: &Mir,
+                                         w: &mut W)
+                                         -> io::Result<()> {
+    write!(w, "    label=<fn {}(", dot::escape_html(&tcx.node_path_str(nid)))?;
+
+    // fn argument types.
+    for (i, arg) in mir.args_iter().enumerate() {
+        if i > 0 {
+            write!(w, ", ")?;
+        }
+        write!(w, "{:?}: {}", Lvalue::Local(arg), escape(&mir.local_decls[arg].ty))?;
+    }
+
+    write!(w, ") -&gt; {}", escape(mir.return_ty))?;
+    write!(w, r#"<br align="left"/>"#)?;
+
+    for local in mir.vars_and_temps_iter() {
+        let decl = &mir.local_decls[local];
+
+        write!(w, "let ")?;
+        if decl.mutability == Mutability::Mut {
+            write!(w, "mut ")?;
+        }
+
+        if let Some(name) = decl.name {
+            write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
+                   Lvalue::Local(local), escape(&decl.ty), name)?;
+        } else {
+            write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
+                   Lvalue::Local(local), escape(&decl.ty))?;
+        }
+    }
+
+    writeln!(w, ">;")
+}
+
+fn node(block: BasicBlock) -> String {
+    format!("bb{}", block.index())
+}
+
+fn escape<T: Debug>(t: &T) -> String {
+    dot::escape_html(&format!("{:?}", t))
+}
diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs
new file mode 100644 (file)
index 0000000..cafc5bc
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+pub mod elaborate_drops;
+pub mod def_use;
+pub mod patch;
+
+mod graphviz;
+mod pretty;
+
+pub use self::pretty::{dump_mir, write_mir_pretty};
+pub use self::graphviz::{write_mir_graphviz};
+pub use self::graphviz::write_node_label as write_graphviz_node_label;
diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs
new file mode 100644 (file)
index 0000000..19f240d
--- /dev/null
@@ -0,0 +1,178 @@
+// 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.
+
+use rustc::ty::Ty;
+use rustc::mir::*;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+
+/// This struct represents a patch to MIR, which can add
+/// new statements and basic blocks and patch over block
+/// terminators.
+pub struct MirPatch<'tcx> {
+    patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
+    new_blocks: Vec<BasicBlockData<'tcx>>,
+    new_statements: Vec<(Location, StatementKind<'tcx>)>,
+    new_locals: Vec<LocalDecl<'tcx>>,
+    resume_block: BasicBlock,
+    next_local: usize,
+}
+
+impl<'tcx> MirPatch<'tcx> {
+    pub fn new(mir: &Mir<'tcx>) -> Self {
+        let mut result = MirPatch {
+            patch_map: IndexVec::from_elem(None, mir.basic_blocks()),
+            new_blocks: vec![],
+            new_statements: vec![],
+            new_locals: vec![],
+            next_local: mir.local_decls.len(),
+            resume_block: START_BLOCK
+        };
+
+        // make sure the MIR we create has a resume block. It is
+        // completely legal to convert jumps to the resume block
+        // to jumps to None, but we occasionally have to add
+        // instructions just before that.
+
+        let mut resume_block = None;
+        let mut resume_stmt_block = None;
+        for (bb, block) in mir.basic_blocks().iter_enumerated() {
+            if let TerminatorKind::Resume = block.terminator().kind {
+                if block.statements.len() > 0 {
+                    resume_stmt_block = Some(bb);
+                } else {
+                    resume_block = Some(bb);
+                }
+                break
+            }
+        }
+        let resume_block = resume_block.unwrap_or_else(|| {
+            result.new_block(BasicBlockData {
+                statements: vec![],
+                terminator: Some(Terminator {
+                    source_info: SourceInfo {
+                        span: mir.span,
+                        scope: ARGUMENT_VISIBILITY_SCOPE
+                    },
+                    kind: TerminatorKind::Resume
+                }),
+                is_cleanup: true
+            })});
+        result.resume_block = resume_block;
+        if let Some(resume_stmt_block) = resume_stmt_block {
+            result.patch_terminator(resume_stmt_block, TerminatorKind::Goto {
+                target: resume_block
+            });
+        }
+        result
+    }
+
+    pub fn resume_block(&self) -> BasicBlock {
+        self.resume_block
+    }
+
+    pub fn is_patched(&self, bb: BasicBlock) -> bool {
+        self.patch_map[bb].is_some()
+    }
+
+    pub fn terminator_loc(&self, mir: &Mir<'tcx>, bb: BasicBlock) -> Location {
+        let offset = match bb.index().checked_sub(mir.basic_blocks().len()) {
+            Some(index) => self.new_blocks[index].statements.len(),
+            None => mir[bb].statements.len()
+        };
+        Location {
+            block: bb,
+            statement_index: offset
+        }
+    }
+
+    pub fn new_temp(&mut self, ty: Ty<'tcx>) -> Local {
+        let index = self.next_local;
+        self.next_local += 1;
+        self.new_locals.push(LocalDecl::new_temp(ty));
+        Local::new(index as usize)
+    }
+
+    pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
+        let block = BasicBlock::new(self.patch_map.len());
+        debug!("MirPatch: new_block: {:?}: {:?}", block, data);
+        self.new_blocks.push(data);
+        self.patch_map.push(None);
+        block
+    }
+
+    pub fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) {
+        assert!(self.patch_map[block].is_none());
+        debug!("MirPatch: patch_terminator({:?}, {:?})", block, new);
+        self.patch_map[block] = Some(new);
+    }
+
+    pub fn add_statement(&mut self, loc: Location, stmt: StatementKind<'tcx>) {
+        debug!("MirPatch: add_statement({:?}, {:?})", loc, stmt);
+        self.new_statements.push((loc, stmt));
+    }
+
+    pub fn add_assign(&mut self, loc: Location, lv: Lvalue<'tcx>, rv: Rvalue<'tcx>) {
+        self.add_statement(loc, StatementKind::Assign(lv, rv));
+    }
+
+    pub fn apply(self, mir: &mut Mir<'tcx>) {
+        debug!("MirPatch: {:?} new temps, starting from index {}: {:?}",
+               self.new_locals.len(), mir.local_decls.len(), self.new_locals);
+        debug!("MirPatch: {} new blocks, starting from index {}",
+               self.new_blocks.len(), mir.basic_blocks().len());
+        mir.basic_blocks_mut().extend(self.new_blocks);
+        mir.local_decls.extend(self.new_locals);
+        for (src, patch) in self.patch_map.into_iter_enumerated() {
+            if let Some(patch) = patch {
+                debug!("MirPatch: patching block {:?}", src);
+                mir[src].terminator_mut().kind = patch;
+            }
+        }
+
+        let mut new_statements = self.new_statements;
+        new_statements.sort_by(|u,v| u.0.cmp(&v.0));
+
+        let mut delta = 0;
+        let mut last_bb = START_BLOCK;
+        for (mut loc, stmt) in new_statements {
+            if loc.block != last_bb {
+                delta = 0;
+                last_bb = loc.block;
+            }
+            debug!("MirPatch: adding statement {:?} at loc {:?}+{}",
+                   stmt, loc, delta);
+            loc.statement_index += delta;
+            let source_info = Self::source_info_for_index(
+                &mir[loc.block], loc
+            );
+            mir[loc.block].statements.insert(
+                loc.statement_index, Statement {
+                    source_info: source_info,
+                    kind: stmt
+                });
+            delta += 1;
+        }
+    }
+
+    pub fn source_info_for_index(data: &BasicBlockData, loc: Location) -> SourceInfo {
+        match data.statements.get(loc.statement_index) {
+            Some(stmt) => stmt.source_info,
+            None => data.terminator().source_info
+        }
+    }
+
+    pub fn source_info_for_location(&self, mir: &Mir, loc: Location) -> SourceInfo {
+        let data = match loc.block.index().checked_sub(mir.basic_blocks().len()) {
+            Some(new) => &self.new_blocks[new],
+            None => &mir[loc.block]
+        };
+        Self::source_info_for_index(data, loc)
+    }
+}
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
new file mode 100644 (file)
index 0000000..35734dc
--- /dev/null
@@ -0,0 +1,311 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+use rustc::mir::*;
+use rustc::mir::transform::MirSource;
+use rustc::ty::TyCtxt;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::indexed_vec::{Idx};
+use std::fmt::Display;
+use std::fs;
+use std::io::{self, Write};
+use std::path::{PathBuf, Path};
+
+const INDENT: &'static str = "    ";
+/// Alignment for lining up comments following MIR statements
+const ALIGN: usize = 40;
+
+/// If the session is properly configured, dumps a human-readable
+/// representation of the mir into:
+///
+/// ```text
+/// rustc.node<node_id>.<pass_name>.<disambiguator>
+/// ```
+///
+/// Output from this function is controlled by passing `-Z dump-mir=<filter>`,
+/// where `<filter>` takes the following forms:
+///
+/// - `all` -- dump MIR for all fns, all passes, all everything
+/// - `substring1&substring2,...` -- `&`-separated list of substrings
+///   that can appear in the pass-name or the `item_path_str` for the given
+///   node-id. If any one of the substrings match, the data is dumped out.
+pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          pass_name: &str,
+                          disambiguator: &Display,
+                          src: MirSource,
+                          mir: &Mir<'tcx>) {
+    let filters = match tcx.sess.opts.debugging_opts.dump_mir {
+        None => return,
+        Some(ref filters) => filters,
+    };
+    let node_id = src.item_id();
+    let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id));
+    let is_matched =
+        filters.split("&")
+               .any(|filter| {
+                   filter == "all" ||
+                       pass_name.contains(filter) ||
+                       node_path.contains(filter)
+               });
+    if !is_matched {
+        return;
+    }
+
+    let promotion_id = match src {
+        MirSource::Promoted(_, id) => format!("-{:?}", id),
+        _ => String::new()
+    };
+
+    let mut file_path = PathBuf::new();
+    if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
+        let p = Path::new(file_dir);
+        file_path.push(p);
+    };
+    let file_name = format!("rustc.node{}{}.{}.{}.mir",
+                            node_id, promotion_id, pass_name, disambiguator);
+    file_path.push(&file_name);
+    let _ = fs::File::create(&file_path).and_then(|mut file| {
+        writeln!(file, "// MIR for `{}`", node_path)?;
+        writeln!(file, "// node_id = {}", node_id)?;
+        writeln!(file, "// pass_name = {}", pass_name)?;
+        writeln!(file, "// disambiguator = {}", disambiguator)?;
+        writeln!(file, "")?;
+        write_mir_fn(tcx, src, mir, &mut file)?;
+        Ok(())
+    });
+}
+
+/// Write out a human-readable textual representation for the given MIR.
+pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
+                                         iter: I,
+                                         w: &mut Write)
+                                         -> io::Result<()>
+    where I: Iterator<Item=DefId>, 'tcx: 'a
+{
+    let mut first = true;
+    for def_id in iter.filter(DefId::is_local) {
+        let mir = &tcx.item_mir(def_id);
+
+        if first {
+            first = false;
+        } else {
+            // Put empty lines between all items
+            writeln!(w, "")?;
+        }
+
+        let id = tcx.hir.as_local_node_id(def_id).unwrap();
+        let src = MirSource::from_node(tcx, id);
+        write_mir_fn(tcx, src, mir, w)?;
+
+        for (i, mir) in mir.promoted.iter_enumerated() {
+            writeln!(w, "")?;
+            write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w)?;
+        }
+    }
+    Ok(())
+}
+
+pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              src: MirSource,
+                              mir: &Mir<'tcx>,
+                              w: &mut Write)
+                              -> io::Result<()> {
+    write_mir_intro(tcx, src, mir, w)?;
+    for block in mir.basic_blocks().indices() {
+        write_basic_block(tcx, block, mir, w)?;
+        if block.index() + 1 != mir.basic_blocks().len() {
+            writeln!(w, "")?;
+        }
+    }
+
+    writeln!(w, "}}")?;
+    Ok(())
+}
+
+/// Write out a human-readable textual representation for the given basic block.
+fn write_basic_block(tcx: TyCtxt,
+                     block: BasicBlock,
+                     mir: &Mir,
+                     w: &mut Write)
+                     -> io::Result<()> {
+    let data = &mir[block];
+
+    // Basic block label at the top.
+    writeln!(w, "{}{:?}: {{", INDENT, block)?;
+
+    // List of statements in the middle.
+    let mut current_location = Location { block: block, statement_index: 0 };
+    for statement in &data.statements {
+        let indented_mir = format!("{0}{0}{1:?};", INDENT, statement);
+        writeln!(w, "{0:1$} // {2}",
+                 indented_mir,
+                 ALIGN,
+                 comment(tcx, statement.source_info))?;
+
+        current_location.statement_index += 1;
+    }
+
+    // Terminator at the bottom.
+    let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind);
+    writeln!(w, "{0:1$} // {2}",
+             indented_terminator,
+             ALIGN,
+             comment(tcx, data.terminator().source_info))?;
+
+    writeln!(w, "{}}}", INDENT)
+}
+
+fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String {
+    format!("scope {} at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
+}
+
+/// Prints user-defined variables in a scope tree.
+///
+/// Returns the total number of variables printed.
+fn write_scope_tree(tcx: TyCtxt,
+                    mir: &Mir,
+                    scope_tree: &FxHashMap<VisibilityScope, Vec<VisibilityScope>>,
+                    w: &mut Write,
+                    parent: VisibilityScope,
+                    depth: usize)
+                    -> io::Result<()> {
+    let indent = depth * INDENT.len();
+
+    let children = match scope_tree.get(&parent) {
+        Some(childs) => childs,
+        None => return Ok(()),
+    };
+
+    for &child in children {
+        let data = &mir.visibility_scopes[child];
+        assert_eq!(data.parent_scope, Some(parent));
+        writeln!(w, "{0:1$}scope {2} {{", "", indent, child.index())?;
+
+        // User variable types (including the user's name in a comment).
+        for local in mir.vars_iter() {
+            let var = &mir.local_decls[local];
+            let (name, source_info) = if var.source_info.unwrap().scope == child {
+                (var.name.unwrap(), var.source_info.unwrap())
+            } else {
+                // Not a variable or not declared in this scope.
+                continue;
+            };
+
+            let mut_str = if var.mutability == Mutability::Mut {
+                "mut "
+            } else {
+                ""
+            };
+
+            let indent = indent + INDENT.len();
+            let indented_var = format!("{0:1$}let {2}{3:?}: {4};",
+                                       INDENT,
+                                       indent,
+                                       mut_str,
+                                       local,
+                                       var.ty);
+            writeln!(w, "{0:1$} // \"{2}\" in {3}",
+                     indented_var,
+                     ALIGN,
+                     name,
+                     comment(tcx, source_info))?;
+        }
+
+        write_scope_tree(tcx, mir, scope_tree, w, child, depth + 1)?;
+
+        writeln!(w, "{0:1$}}}", "", depth * INDENT.len())?;
+    }
+
+    Ok(())
+}
+
+/// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
+/// local variables (both user-defined bindings and compiler temporaries).
+fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             src: MirSource,
+                             mir: &Mir,
+                             w: &mut Write)
+                             -> io::Result<()> {
+    write_mir_sig(tcx, src, mir, w)?;
+    writeln!(w, " {{")?;
+
+    // construct a scope tree and write it out
+    let mut scope_tree: FxHashMap<VisibilityScope, Vec<VisibilityScope>> = FxHashMap();
+    for (index, scope_data) in mir.visibility_scopes.iter().enumerate() {
+        if let Some(parent) = scope_data.parent_scope {
+            scope_tree.entry(parent)
+                      .or_insert(vec![])
+                      .push(VisibilityScope::new(index));
+        } else {
+            // Only the argument scope has no parent, because it's the root.
+            assert_eq!(index, ARGUMENT_VISIBILITY_SCOPE.index());
+        }
+    }
+
+    // Print return pointer
+    let indented_retptr = format!("{}let mut {:?}: {};",
+                                  INDENT,
+                                  RETURN_POINTER,
+                                  mir.return_ty);
+    writeln!(w, "{0:1$} // return pointer",
+             indented_retptr,
+             ALIGN)?;
+
+    write_scope_tree(tcx, mir, &scope_tree, w, ARGUMENT_VISIBILITY_SCOPE, 1)?;
+
+    write_temp_decls(mir, w)?;
+
+    // Add an empty line before the first block is printed.
+    writeln!(w, "")?;
+
+    Ok(())
+}
+
+fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
+                 -> io::Result<()>
+{
+    match src {
+        MirSource::Fn(_) => write!(w, "fn")?,
+        MirSource::Const(_) => write!(w, "const")?,
+        MirSource::Static(_, hir::MutImmutable) => write!(w, "static")?,
+        MirSource::Static(_, hir::MutMutable) => write!(w, "static mut")?,
+        MirSource::Promoted(_, i) => write!(w, "{:?} in", i)?
+    }
+
+    write!(w, " {}", tcx.node_path_str(src.item_id()))?;
+
+    if let MirSource::Fn(_) = src {
+        write!(w, "(")?;
+
+        // fn argument types.
+        for (i, arg) in mir.args_iter().enumerate() {
+            if i != 0 {
+                write!(w, ", ")?;
+            }
+            write!(w, "{:?}: {}", Lvalue::Local(arg), mir.local_decls[arg].ty)?;
+        }
+
+        write!(w, ") -> {}", mir.return_ty)
+    } else {
+        assert_eq!(mir.arg_count, 0);
+        write!(w, ": {} =", mir.return_ty)
+    }
+}
+
+fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
+    // Compiler-introduced temporary types.
+    for temp in mir.temps_iter() {
+        writeln!(w, "{}let mut {:?}: {};", INDENT, temp, mir.local_decls[temp].ty)?;
+    }
+
+    Ok(())
+}
index b2d51be5bf72095bc3b4199dec8af37c285ae3e9..421181c68c4cda90eef45bf85fe12ab59a27e424 100644 (file)
@@ -87,14 +87,19 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) {
                 self.with_context(Closure, |v| v.visit_nested_body(b));
             }
             hir::ExprBreak(label, ref opt_expr) => {
-                let loop_id = match label.loop_id.into() {
-                    Ok(loop_id) => loop_id,
-                    Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
-                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
-                        self.emit_unlabled_cf_in_while_condition(e.span, "break");
-                        ast::DUMMY_NODE_ID
-                    },
-                    Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
+                let loop_id = match label.target_id {
+                    hir::ScopeTarget::Block(_) => return,
+                    hir::ScopeTarget::Loop(loop_res) => {
+                        match loop_res.into() {
+                            Ok(loop_id) => loop_id,
+                            Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
+                            Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
+                                self.emit_unlabled_cf_in_while_condition(e.span, "break");
+                                ast::DUMMY_NODE_ID
+                            },
+                            Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
+                        }
+                    }
                 };
 
                 if opt_expr.is_some() {
@@ -124,7 +129,9 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) {
                 self.require_loop("break", e.span);
             }
             hir::ExprAgain(label) => {
-                if let Err(hir::LoopIdError::UnlabeledCfInWhileCondition) = label.loop_id.into() {
+                if let hir::ScopeTarget::Loop(
+                    hir::LoopIdResult::Err(
+                        hir::LoopIdError::UnlabeledCfInWhileCondition)) = label.target_id {
                     self.emit_unlabled_cf_in_while_condition(e.span, "continue");
                 }
                 self.require_loop("continue", e.span)
index 72347f1616eb69e045f145d87b8d1eac4b8af40f..e32ec25a7e8f77857f40bf5242a5529ad17096e2 100644 (file)
 
 pub mod diagnostics;
 
+////////////////////////////////////////////////////////////////////////////////
+/// Visitor used to determine if pub(restricted) is used anywhere in the crate.
+///
+/// This is done so that `private_in_public` warnings can be turned into hard errors
+/// in crates that have been updated to use pub(restricted).
+////////////////////////////////////////////////////////////////////////////////
+struct PubRestrictedVisitor<'a, 'tcx: 'a> {
+    tcx:  TyCtxt<'a, 'tcx, 'tcx>,
+    has_pub_restricted: bool,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::All(&self.tcx.hir)
+    }
+    fn visit_vis(&mut self, vis: &'tcx hir::Visibility) {
+        self.has_pub_restricted = self.has_pub_restricted || vis.is_pub_restricted();
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 /// The embargo visitor, used to determine the exports of the ast
 ////////////////////////////////////////////////////////////////////////////////
@@ -891,6 +911,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
     required_visibility: ty::Visibility,
     /// The visibility of the least visible component that has been visited
     min_visibility: ty::Visibility,
+    has_pub_restricted: bool,
     has_old_errors: bool,
 }
 
@@ -951,7 +972,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                     self.min_visibility = vis;
                 }
                 if !vis.is_at_least(self.required_visibility, self.tcx) {
-                    if self.tcx.sess.features.borrow().pub_restricted || self.has_old_errors {
+                    if self.has_pub_restricted || self.has_old_errors {
                         let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
                             "private type `{}` in public interface", ty);
                         err.span_label(self.span, &format!("can't leak private type"));
@@ -986,7 +1007,7 @@ fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
                 self.min_visibility = vis;
             }
             if !vis.is_at_least(self.required_visibility, self.tcx) {
-                if self.tcx.sess.features.borrow().pub_restricted || self.has_old_errors {
+                if self.has_pub_restricted || self.has_old_errors {
                     struct_span_err!(self.tcx.sess, self.span, E0445,
                                      "private trait `{}` in public interface", trait_ref)
                         .span_label(self.span, &format!(
@@ -1008,6 +1029,7 @@ fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
 
 struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    has_pub_restricted: bool,
     old_error_set: &'a NodeSet,
     inner_visibility: ty::Visibility,
 }
@@ -1044,6 +1066,7 @@ fn check(&self, item_id: ast::NodeId, required_visibility: ty::Visibility)
             span: self.tcx.hir.span(item_id),
             min_visibility: ty::Visibility::Public,
             required_visibility: required_visibility,
+            has_pub_restricted: self.has_pub_restricted,
             has_old_errors: has_old_errors,
         }
     }
@@ -1227,9 +1250,20 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
         intravisit::walk_crate(&mut visitor, krate);
 
+
+        let has_pub_restricted = {
+            let mut pub_restricted_visitor = PubRestrictedVisitor {
+                tcx: tcx,
+                has_pub_restricted: false
+            };
+            intravisit::walk_crate(&mut pub_restricted_visitor, krate);
+            pub_restricted_visitor.has_pub_restricted
+        };
+
         // Check for private types and traits in public interfaces
         let mut visitor = PrivateItemsInPublicInterfacesVisitor {
             tcx: tcx,
+            has_pub_restricted: has_pub_restricted,
             old_error_set: &visitor.old_error_set,
             inner_visibility: ty::Visibility::Public,
         };
index 3d66e5a3007874cecbeaeeff98ddd43e33b481c7..06c5150fd13ade909458604075f3dcacd69a2b9c 100644 (file)
@@ -12,5 +12,8 @@ crate-type = ["dylib"]
 log = { path = "../liblog" }
 rustc = { path = "../librustc" }
 syntax = { path = "../libsyntax" }
-serialize = { path = "../libserialize" }
-syntax_pos = { path = "../libsyntax_pos" }
\ No newline at end of file
+syntax_pos = { path = "../libsyntax_pos" }
+rls-data = "0.1"
+rls-span = "0.1"
+# FIXME(#40527) should move rustc serialize out of tree
+rustc-serialize = "0.3"
index 0fd95500422ff193af8a29aa1f8ea615657eb775..59340ae87ee5da6e607b7e48ce976efd988b9228 100644 (file)
@@ -13,6 +13,8 @@
 use super::external_data::*;
 use super::dump::Dump;
 
+use rls_data::{SpanData, CratePreludeData};
+
 pub struct CsvDumper<'b, W: 'b> {
     output: &'b mut W
 }
@@ -429,6 +431,6 @@ fn make_values_str(pairs: &[(&'static str, &str)]) -> String {
 fn span_extent_str(span: SpanData) -> String {
     format!("file_name,\"{}\",file_line,{},file_col,{},byte_start,{},\
              file_line_end,{},file_col_end,{},byte_end,{}",
-             span.file_name, span.line_start, span.column_start, span.byte_start,
-             span.line_end, span.column_end, span.byte_end)
+             span.file_name.to_str().unwrap(), span.line_start.0, span.column_start.0,
+             span.byte_start, span.line_end.0, span.column_end.0, span.byte_end)
 }
index 6caf81380e40dad51f8c33c1d90a51c7dd5f7065..d4ded71a3339091fa2b53af1e650b0f3770ef25e 100644 (file)
@@ -18,6 +18,8 @@
 use syntax::ast::{self, Attribute, NodeId};
 use syntax_pos::Span;
 
+use rls_data::ExternalCrateData;
+
 pub struct CrateData {
     pub name: String,
     pub number: u32,
@@ -26,7 +28,7 @@ pub struct CrateData {
 
 /// Data for any entity in the Rust language. The actual data contained varies
 /// with the kind of entity being queried. See the nested structs for details.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub enum Data {
     /// Data for Enums.
     EnumData(EnumData),
@@ -77,7 +79,7 @@ pub enum Data {
     VariableRefData(VariableRefData),
 }
 
-#[derive(Eq, PartialEq, Clone, Copy, Debug, RustcEncodable)]
+#[derive(Eq, PartialEq, Clone, Copy, Debug)]
 pub enum Visibility {
     Public,
     Restricted,
@@ -107,7 +109,7 @@ fn from(v: &'a hir::Visibility) -> Visibility {
 }
 
 /// Data for the prelude of a crate.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct CratePreludeData {
     pub crate_name: String,
     pub crate_root: String,
@@ -115,16 +117,8 @@ pub struct CratePreludeData {
     pub span: Span,
 }
 
-/// Data for external crates in the prelude of a crate.
-#[derive(Debug, RustcEncodable)]
-pub struct ExternalCrateData {
-    pub name: String,
-    pub num: CrateNum,
-    pub file_name: String,
-}
-
 /// Data for enum declarations.
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct EnumData {
     pub id: NodeId,
     pub name: String,
@@ -140,7 +134,7 @@ pub struct EnumData {
 }
 
 /// Data for extern crates.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct ExternCrateData {
     pub id: NodeId,
     pub name: String,
@@ -151,7 +145,7 @@ pub struct ExternCrateData {
 }
 
 /// Data about a function call.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct FunctionCallData {
     pub span: Span,
     pub scope: NodeId,
@@ -159,7 +153,7 @@ pub struct FunctionCallData {
 }
 
 /// Data for all kinds of functions and methods.
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct FunctionData {
     pub id: NodeId,
     pub name: String,
@@ -176,14 +170,14 @@ pub struct FunctionData {
 }
 
 /// Data about a function call.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct FunctionRefData {
     pub span: Span,
     pub scope: NodeId,
     pub ref_id: DefId,
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct ImplData {
     pub id: NodeId,
     pub span: Span,
@@ -192,7 +186,7 @@ pub struct ImplData {
     pub self_ref: Option<DefId>,
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 // FIXME: this struct should not exist. However, removing it requires heavy
 // refactoring of dump_visitor.rs. See PR 31838 for more info.
 pub struct ImplData2 {
@@ -206,7 +200,7 @@ pub struct ImplData2 {
     pub self_ref: Option<TypeRefData>,
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct InheritanceData {
     pub span: Span,
     pub base_id: DefId,
@@ -214,7 +208,7 @@ pub struct InheritanceData {
 }
 
 /// Data about a macro declaration.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct MacroData {
     pub span: Span,
     pub name: String,
@@ -223,7 +217,7 @@ pub struct MacroData {
 }
 
 /// Data about a macro use.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct MacroUseData {
     pub span: Span,
     pub name: String,
@@ -236,7 +230,7 @@ pub struct MacroUseData {
 }
 
 /// Data about a method call.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct MethodCallData {
     pub span: Span,
     pub scope: NodeId,
@@ -245,7 +239,7 @@ pub struct MethodCallData {
 }
 
 /// Data for method declarations (methods with a body are treated as functions).
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct MethodData {
     pub id: NodeId,
     pub name: String,
@@ -262,7 +256,7 @@ pub struct MethodData {
 }
 
 /// Data for modules.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct ModData {
     pub id: NodeId,
     pub name: String,
@@ -278,7 +272,7 @@ pub struct ModData {
 }
 
 /// Data for a reference to a module.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct ModRefData {
     pub span: Span,
     pub scope: NodeId,
@@ -286,7 +280,7 @@ pub struct ModRefData {
     pub qualname: String
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct StructData {
     pub span: Span,
     pub name: String,
@@ -302,7 +296,7 @@ pub struct StructData {
     pub attributes: Vec<Attribute>,
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct StructVariantData {
     pub span: Span,
     pub name: String,
@@ -317,7 +311,7 @@ pub struct StructVariantData {
     pub attributes: Vec<Attribute>,
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct TraitData {
     pub span: Span,
     pub id: NodeId,
@@ -332,7 +326,7 @@ pub struct TraitData {
     pub attributes: Vec<Attribute>,
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct TupleVariantData {
     pub span: Span,
     pub id: NodeId,
@@ -348,7 +342,7 @@ pub struct TupleVariantData {
 }
 
 /// Data for a typedef.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct TypeDefData {
     pub id: NodeId,
     pub name: String,
@@ -363,7 +357,7 @@ pub struct TypeDefData {
 }
 
 /// Data for a reference to a type or trait.
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct TypeRefData {
     pub span: Span,
     pub scope: NodeId,
@@ -371,7 +365,7 @@ pub struct TypeRefData {
     pub qualname: String,
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct UseData {
     pub id: NodeId,
     pub span: Span,
@@ -381,7 +375,7 @@ pub struct UseData {
     pub visibility: Visibility,
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct UseGlobData {
     pub id: NodeId,
     pub span: Span,
@@ -391,7 +385,7 @@ pub struct UseGlobData {
 }
 
 /// Data for local and global variables (consts and statics).
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct VariableData {
     pub id: NodeId,
     pub kind: VariableKind,
@@ -408,7 +402,7 @@ pub struct VariableData {
     pub attributes: Vec<Attribute>,
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub enum VariableKind {
     Static,
     Const,
@@ -418,7 +412,7 @@ pub enum VariableKind {
 
 /// Data for the use of some item (e.g., the use of a local variable, which
 /// will refer to that variables declaration (by ref_id)).
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct VariableRefData {
     pub name: String,
     pub span: Span,
@@ -430,7 +424,7 @@ pub struct VariableRefData {
 /// Encodes information about the signature of a definition. This should have
 /// enough information to create a nice display about a definition without
 /// access to the source code.
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct Signature {
     pub span: Span,
     pub text: String,
@@ -444,7 +438,7 @@ pub struct Signature {
 
 /// An element of a signature. `start` and `end` are byte offsets into the `text`
 /// of the parent `Signature`.
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct SigElement {
     pub id: DefId,
     pub start: usize,
index 18241b394cc17474986d0b9df95d53daa4d7b5dd..84e1fb03f624e821068f2111b3fcefc67ee51eeb 100644 (file)
@@ -10,6 +10,8 @@
 
 use super::external_data::*;
 
+use rls_data::CratePreludeData;
+
 pub trait Dump {
     fn crate_prelude(&mut self, CratePreludeData) {}
     fn enum_data(&mut self, EnumData) {}
index 61956e5cd9d66e4abfd1e411e7b30d1a7ccfedf8..f2aa89ba4b66e8bc9bffdb1523c3ac52c6eb58b6 100644 (file)
@@ -29,7 +29,7 @@
 
 use rustc::hir;
 use rustc::hir::def::Def;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::map::{Node, NodeItem};
 use rustc::session::Session;
 use rustc::ty::{self, TyCtxt, AssociatedItemContainer};
@@ -54,6 +54,8 @@
 use super::span_utils::SpanUtils;
 use super::recorder;
 
+use rls_data::ExternalCrateData;
+
 macro_rules! down_cast_data {
     ($id:ident, $kind:ident, $sp:expr) => {
         let $id = if let super::Data::$kind(data) = $id {
@@ -137,7 +139,7 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
             let lo_loc = self.span.sess.codemap().lookup_char_pos(c.span.lo);
             ExternalCrateData {
                 name: c.name,
-                num: CrateNum::from_u32(c.number),
+                num: c.number,
                 file_name: SpanUtils::make_path_string(&lo_loc.file.name),
             }
         }).collect();
index f038c2dc298ad1fdce8b0bc97905239b19f2f38b..6fd2de97767e18d318a44257424ee7b379a48843 100644 (file)
@@ -18,6 +18,9 @@
 
 use data::{self, Visibility, SigElement};
 
+use rls_data::{SpanData, CratePreludeData, Attribute};
+use rls_span::{Column, Row};
+
 // FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet
 pub trait Lower {
     type Target;
@@ -35,41 +38,19 @@ pub fn null_def_id() -> DefId {
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable)]
-pub struct SpanData {
-    pub file_name: String,
-    pub byte_start: u32,
-    pub byte_end: u32,
-    /// 1-based.
-    pub line_start: usize,
-    pub line_end: usize,
-    /// 1-based, character offset.
-    pub column_start: usize,
-    pub column_end: usize,
-}
-
-impl SpanData {
-    pub fn from_span(span: Span, cm: &CodeMap) -> SpanData {
-        let start = cm.lookup_char_pos(span.lo);
-        let end = cm.lookup_char_pos(span.hi);
-
-        SpanData {
-            file_name: start.file.name.clone(),
-            byte_start: span.lo.0,
-            byte_end: span.hi.0,
-            line_start: start.line,
-            line_end: end.line,
-            column_start: start.col.0 + 1,
-            column_end: end.col.0 + 1,
-        }
-    }
-}
+pub fn span_from_span(span: Span, cm: &CodeMap) -> SpanData {
+    let start = cm.lookup_char_pos(span.lo);
+    let end = cm.lookup_char_pos(span.hi);
 
-/// Represent an arbitrary attribute on a code element
-#[derive(Clone, Debug, RustcEncodable)]
-pub struct Attribute {
-    value: String,
-    span: SpanData,
+    SpanData {
+        file_name: start.file.name.clone().into(),
+        byte_start: span.lo.0,
+        byte_end: span.hi.0,
+        line_start: Row::new_one_indexed(start.line as u32),
+        line_end: Row::new_one_indexed(end.line as u32),
+        column_start: Column::new_one_indexed(start.col.0 as u32 + 1),
+        column_end: Column::new_one_indexed(end.col.0 as u32 + 1),
+    }
 }
 
 impl Lower for Vec<ast::Attribute> {
@@ -91,20 +72,12 @@ fn lower(self, tcx: TyCtxt) -> Vec<Attribute> {
 
             Attribute {
                 value: value,
-                span: SpanData::from_span(attr.span, tcx.sess.codemap()),
+                span: span_from_span(attr.span, tcx.sess.codemap()),
             }
         }).collect()
     }
 }
 
-#[derive(Debug, RustcEncodable)]
-pub struct CratePreludeData {
-    pub crate_name: String,
-    pub crate_root: String,
-    pub external_crates: Vec<data::ExternalCrateData>,
-    pub span: SpanData,
-}
-
 impl Lower for data::CratePreludeData {
     type Target = CratePreludeData;
 
@@ -113,13 +86,13 @@ fn lower(self, tcx: TyCtxt) -> CratePreludeData {
             crate_name: self.crate_name,
             crate_root: self.crate_root,
             external_crates: self.external_crates,
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
         }
     }
 }
 
 /// Data for enum declarations.
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct EnumData {
     pub id: DefId,
     pub value: String,
@@ -143,7 +116,7 @@ fn lower(self, tcx: TyCtxt) -> EnumData {
             name: self.name,
             value: self.value,
             qualname: self.qualname,
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(),
             visibility: self.visibility,
@@ -155,7 +128,7 @@ fn lower(self, tcx: TyCtxt) -> EnumData {
 }
 
 /// Data for extern crates.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct ExternCrateData {
     pub id: DefId,
     pub name: String,
@@ -174,14 +147,14 @@ fn lower(self, tcx: TyCtxt) -> ExternCrateData {
             name: self.name,
             crate_num: self.crate_num,
             location: self.location,
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
         }
     }
 }
 
 /// Data about a function call.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct FunctionCallData {
     pub span: SpanData,
     pub scope: DefId,
@@ -193,7 +166,7 @@ impl Lower for data::FunctionCallData {
 
     fn lower(self, tcx: TyCtxt) -> FunctionCallData {
         FunctionCallData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             ref_id: self.ref_id,
         }
@@ -201,7 +174,7 @@ fn lower(self, tcx: TyCtxt) -> FunctionCallData {
 }
 
 /// Data for all kinds of functions and methods.
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct FunctionData {
     pub id: DefId,
     pub name: String,
@@ -226,7 +199,7 @@ fn lower(self, tcx: TyCtxt) -> FunctionData {
             name: self.name,
             qualname: self.qualname,
             declaration: self.declaration,
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             value: self.value,
             visibility: self.visibility,
@@ -239,7 +212,7 @@ fn lower(self, tcx: TyCtxt) -> FunctionData {
 }
 
 /// Data about a function call.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct FunctionRefData {
     pub span: SpanData,
     pub scope: DefId,
@@ -251,13 +224,13 @@ impl Lower for data::FunctionRefData {
 
     fn lower(self, tcx: TyCtxt) -> FunctionRefData {
         FunctionRefData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             ref_id: self.ref_id,
         }
     }
 }
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct ImplData {
     pub id: DefId,
     pub span: SpanData,
@@ -272,7 +245,7 @@ impl Lower for data::ImplData {
     fn lower(self, tcx: TyCtxt) -> ImplData {
         ImplData {
             id: make_def_id(self.id, &tcx.hir),
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             trait_ref: self.trait_ref,
             self_ref: self.self_ref,
@@ -280,7 +253,7 @@ fn lower(self, tcx: TyCtxt) -> ImplData {
     }
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct InheritanceData {
     pub span: SpanData,
     pub base_id: DefId,
@@ -292,7 +265,7 @@ impl Lower for data::InheritanceData {
 
     fn lower(self, tcx: TyCtxt) -> InheritanceData {
         InheritanceData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             base_id: self.base_id,
             deriv_id: make_def_id(self.deriv_id, &tcx.hir)
         }
@@ -300,7 +273,7 @@ fn lower(self, tcx: TyCtxt) -> InheritanceData {
 }
 
 /// Data about a macro declaration.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct MacroData {
     pub span: SpanData,
     pub name: String,
@@ -313,7 +286,7 @@ impl Lower for data::MacroData {
 
     fn lower(self, tcx: TyCtxt) -> MacroData {
         MacroData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             name: self.name,
             qualname: self.qualname,
             docs: self.docs,
@@ -322,7 +295,7 @@ fn lower(self, tcx: TyCtxt) -> MacroData {
 }
 
 /// Data about a macro use.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct MacroUseData {
     pub span: SpanData,
     pub name: String,
@@ -338,17 +311,17 @@ impl Lower for data::MacroUseData {
 
     fn lower(self, tcx: TyCtxt) -> MacroUseData {
         MacroUseData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             name: self.name,
             qualname: self.qualname,
-            callee_span: SpanData::from_span(self.callee_span, tcx.sess.codemap()),
+            callee_span: span_from_span(self.callee_span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
         }
     }
 }
 
 /// Data about a method call.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct MethodCallData {
     pub span: SpanData,
     pub scope: DefId,
@@ -361,7 +334,7 @@ impl Lower for data::MethodCallData {
 
     fn lower(self, tcx: TyCtxt) -> MethodCallData {
         MethodCallData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             ref_id: self.ref_id,
             decl_id: self.decl_id,
@@ -370,7 +343,7 @@ fn lower(self, tcx: TyCtxt) -> MethodCallData {
 }
 
 /// Data for method declarations (methods with a body are treated as functions).
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct MethodData {
     pub id: DefId,
     pub name: String,
@@ -391,7 +364,7 @@ impl Lower for data::MethodData {
 
     fn lower(self, tcx: TyCtxt) -> MethodData {
         MethodData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             name: self.name,
             scope: make_def_id(self.scope, &tcx.hir),
             id: make_def_id(self.id, &tcx.hir),
@@ -408,7 +381,7 @@ fn lower(self, tcx: TyCtxt) -> MethodData {
 }
 
 /// Data for modules.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct ModData {
     pub id: DefId,
     pub name: String,
@@ -431,7 +404,7 @@ fn lower(self, tcx: TyCtxt) -> ModData {
             id: make_def_id(self.id, &tcx.hir),
             name: self.name,
             qualname: self.qualname,
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             filename: self.filename,
             items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(),
@@ -444,7 +417,7 @@ fn lower(self, tcx: TyCtxt) -> ModData {
 }
 
 /// Data for a reference to a module.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct ModRefData {
     pub span: SpanData,
     pub scope: DefId,
@@ -457,7 +430,7 @@ impl Lower for data::ModRefData {
 
     fn lower(self, tcx: TyCtxt) -> ModRefData {
         ModRefData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             ref_id: self.ref_id,
             qualname: self.qualname,
@@ -465,7 +438,7 @@ fn lower(self, tcx: TyCtxt) -> ModRefData {
     }
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct StructData {
     pub span: SpanData,
     pub name: String,
@@ -486,7 +459,7 @@ impl Lower for data::StructData {
 
     fn lower(self, tcx: TyCtxt) -> StructData {
         StructData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             name: self.name,
             id: make_def_id(self.id, &tcx.hir),
             ctor_id: make_def_id(self.ctor_id, &tcx.hir),
@@ -502,7 +475,7 @@ fn lower(self, tcx: TyCtxt) -> StructData {
     }
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct StructVariantData {
     pub span: SpanData,
     pub name: String,
@@ -522,7 +495,7 @@ impl Lower for data::StructVariantData {
 
     fn lower(self, tcx: TyCtxt) -> StructVariantData {
         StructVariantData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             name: self.name,
             id: make_def_id(self.id, &tcx.hir),
             qualname: self.qualname,
@@ -537,7 +510,7 @@ fn lower(self, tcx: TyCtxt) -> StructVariantData {
     }
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct TraitData {
     pub span: SpanData,
     pub name: String,
@@ -557,7 +530,7 @@ impl Lower for data::TraitData {
 
     fn lower(self, tcx: TyCtxt) -> TraitData {
         TraitData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             name: self.name,
             id: make_def_id(self.id, &tcx.hir),
             qualname: self.qualname,
@@ -572,7 +545,7 @@ fn lower(self, tcx: TyCtxt) -> TraitData {
     }
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct TupleVariantData {
     pub span: SpanData,
     pub id: DefId,
@@ -592,7 +565,7 @@ impl Lower for data::TupleVariantData {
 
     fn lower(self, tcx: TyCtxt) -> TupleVariantData {
         TupleVariantData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             id: make_def_id(self.id, &tcx.hir),
             name: self.name,
             qualname: self.qualname,
@@ -608,7 +581,7 @@ fn lower(self, tcx: TyCtxt) -> TupleVariantData {
 }
 
 /// Data for a typedef.
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct TypeDefData {
     pub id: DefId,
     pub name: String,
@@ -629,7 +602,7 @@ fn lower(self, tcx: TyCtxt) -> TypeDefData {
         TypeDefData {
             id: make_def_id(self.id, &tcx.hir),
             name: self.name,
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             qualname: self.qualname,
             value: self.value,
             visibility: self.visibility,
@@ -642,7 +615,7 @@ fn lower(self, tcx: TyCtxt) -> TypeDefData {
 }
 
 /// Data for a reference to a type or trait.
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct TypeRefData {
     pub span: SpanData,
     pub scope: DefId,
@@ -655,7 +628,7 @@ impl Lower for data::TypeRefData {
 
     fn lower(self, tcx: TyCtxt) -> TypeRefData {
         TypeRefData {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             ref_id: self.ref_id,
             qualname: self.qualname,
@@ -663,7 +636,7 @@ fn lower(self, tcx: TyCtxt) -> TypeRefData {
     }
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct UseData {
     pub id: DefId,
     pub span: SpanData,
@@ -679,7 +652,7 @@ impl Lower for data::UseData {
     fn lower(self, tcx: TyCtxt) -> UseData {
         UseData {
             id: make_def_id(self.id, &tcx.hir),
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             name: self.name,
             mod_id: self.mod_id,
             scope: make_def_id(self.scope, &tcx.hir),
@@ -688,7 +661,7 @@ fn lower(self, tcx: TyCtxt) -> UseData {
     }
 }
 
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct UseGlobData {
     pub id: DefId,
     pub span: SpanData,
@@ -703,7 +676,7 @@ impl Lower for data::UseGlobData {
     fn lower(self, tcx: TyCtxt) -> UseGlobData {
         UseGlobData {
             id: make_def_id(self.id, &tcx.hir),
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             names: self.names,
             scope: make_def_id(self.scope, &tcx.hir),
             visibility: self.visibility,
@@ -712,7 +685,7 @@ fn lower(self, tcx: TyCtxt) -> UseGlobData {
 }
 
 /// Data for local and global variables (consts and statics).
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct VariableData {
     pub id: DefId,
     pub name: String,
@@ -738,7 +711,7 @@ fn lower(self, tcx: TyCtxt) -> VariableData {
             kind: self.kind,
             name: self.name,
             qualname: self.qualname,
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             value: self.value,
             type_value: self.type_value,
@@ -753,7 +726,7 @@ fn lower(self, tcx: TyCtxt) -> VariableData {
 
 /// Data for the use of some item (e.g., the use of a local variable, which
 /// will refer to that variables declaration (by ref_id)).
-#[derive(Debug, RustcEncodable)]
+#[derive(Debug)]
 pub struct VariableRefData {
     pub name: String,
     pub span: SpanData,
@@ -767,14 +740,14 @@ impl Lower for data::VariableRefData {
     fn lower(self, tcx: TyCtxt) -> VariableRefData {
         VariableRefData {
             name: self.name,
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             scope: make_def_id(self.scope, &tcx.hir),
             ref_id: self.ref_id,
         }
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable)]
+#[derive(Clone, Debug)]
 pub struct Signature {
     pub span: SpanData,
     pub text: String,
@@ -791,7 +764,7 @@ impl Lower for data::Signature {
 
     fn lower(self, tcx: TyCtxt) -> Signature {
         Signature {
-            span: SpanData::from_span(self.span, tcx.sess.codemap()),
+            span: span_from_span(self.span, tcx.sess.codemap()),
             text: self.text,
             ident_start: self.ident_start,
             ident_end: self.ident_end,
index 277535f9e651373318c162830e7c3889a2451bf7..41221ad986379b7f720875fa5ce997d95675dd8a 100644 (file)
 
 use std::io::Write;
 
-use rustc::hir::def_id::DefId;
 use rustc_serialize::json::as_json;
 
 use external_data::*;
-use data::{VariableKind, Visibility, SigElement};
+use data::{VariableKind, Visibility};
 use dump::Dump;
-use super::Format;
+use json_dumper::id_from_def_id;
+
+use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData};
 
 
 // A dumper to dump a restricted set of JSON information, designed for use with
@@ -24,8 +25,7 @@
 // information here, and (for example) generate Rustdoc URLs, but don't need
 // information for navigating the source of the crate.
 // Relative to the regular JSON save-analysis info, this form is filtered to
-// remove non-visible items, but includes some extra info for items (e.g., the
-// parent field for finding the struct to which a field belongs).
+// remove non-visible items.
 pub struct JsonApiDumper<'b, W: Write + 'b> {
     output: &'b mut W,
     result: Analysis,
@@ -48,7 +48,7 @@ fn drop(&mut self) {
 macro_rules! impl_fn {
     ($fn_name: ident, $data_type: ident, $bucket: ident) => {
         fn $fn_name(&mut self, data: $data_type) {
-            if let Some(datum) = From::from(data) {
+            if let Some(datum) = data.into() {
                 self.result.$bucket.push(datum);
             }
         }
@@ -77,11 +77,11 @@ fn crate_prelude(&mut self, data: CratePreludeData) {
 
     fn impl_data(&mut self, data: ImplData) {
         if data.self_ref.is_some() {
-            self.result.relations.push(From::from(data));
+            self.result.relations.push(data.into());
         }
     }
     fn inheritance(&mut self, data: InheritanceData) {
-        self.result.relations.push(From::from(data));
+        self.result.relations.push(data.into());
     }
 }
 
@@ -90,426 +90,261 @@ fn inheritance(&mut self, data: InheritanceData) {
 // method, but not the supplied method). In both cases, we are currently
 // ignoring it.
 
-#[derive(Debug, RustcEncodable)]
-struct Analysis {
-    kind: Format,
-    prelude: Option<CratePreludeData>,
-    imports: Vec<Import>,
-    defs: Vec<Def>,
-    relations: Vec<Relation>,
-    // These two fields are dummies so that clients can parse the two kinds of
-    // JSON data in the same way.
-    refs: Vec<()>,
-    macro_refs: Vec<()>,
-}
-
-impl Analysis {
-    fn new() -> Analysis {
-        Analysis {
-            kind: Format::JsonApi,
-            prelude: None,
-            imports: vec![],
-            defs: vec![],
-            relations: vec![],
-            refs: vec![],
-            macro_refs: vec![],
-        }
-    }
-}
-
-// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
-// we use our own Id which is the same, but without the newtype.
-#[derive(Debug, RustcEncodable)]
-struct Id {
-    krate: u32,
-    index: u32,
-}
-
-impl From<DefId> for Id {
-    fn from(id: DefId) -> Id {
-        Id {
-            krate: id.krate.as_u32(),
-            index: id.index.as_u32(),
-        }
-    }
-}
-
-#[derive(Debug, RustcEncodable)]
-struct Import {
-    kind: ImportKind,
-    id: Id,
-    span: SpanData,
-    name: String,
-    value: String,
-}
-
-#[derive(Debug, RustcEncodable)]
-enum ImportKind {
-    Use,
-    GlobUse,
-}
-
-impl From<UseData> for Option<Import> {
-    fn from(data: UseData) -> Option<Import> {
-        match data.visibility {
+impl Into<Option<Import>> for UseData {
+    fn into(self) -> Option<Import> {
+        match self.visibility {
             Visibility::Public => Some(Import {
                 kind: ImportKind::Use,
-                id: From::from(data.id),
-                span: data.span,
-                name: data.name,
+                ref_id: self.mod_id.map(|id| id_from_def_id(id)),
+                span: self.span,
+                name: self.name,
                 value: String::new(),
             }),
             _ => None,
         }
     }
 }
-impl From<UseGlobData> for Option<Import> {
-    fn from(data: UseGlobData) -> Option<Import> {
-        match data.visibility {
+impl Into<Option<Import>> for UseGlobData {
+    fn into(self) -> Option<Import> {
+        match self.visibility {
             Visibility::Public => Some(Import {
                 kind: ImportKind::GlobUse,
-                id: From::from(data.id),
-                span: data.span,
+                ref_id: None,
+                span: self.span,
                 name: "*".to_owned(),
-                value: data.names.join(", "),
+                value: self.names.join(", "),
             }),
             _ => None,
         }
     }
 }
 
-#[derive(Debug, RustcEncodable)]
-struct Def {
-    kind: DefKind,
-    id: Id,
-    span: SpanData,
-    name: String,
-    qualname: String,
-    value: String,
-    parent: Option<Id>,
-    children: Vec<Id>,
-    decl_id: Option<Id>,
-    docs: String,
-    sig: Option<JsonSignature>,
-}
-
-#[derive(Debug, RustcEncodable)]
-enum DefKind {
-    // value = variant names
-    Enum,
-    // value = enum name + variant name + types
-    Tuple,
-    // value = [enum name +] name + fields
-    Struct,
-    // value = signature
-    Trait,
-    // value = type + generics
-    Function,
-    // value = type + generics
-    Method,
-    // No id, no value.
-    Macro,
-    // value = file_name
-    Mod,
-    // value = aliased type
-    Type,
-    // value = type and init expression (for all variable kinds).
-    Static,
-    Const,
-    Field,
-}
-
-impl From<EnumData> for Option<Def> {
-    fn from(data: EnumData) -> Option<Def> {
-        match data.visibility {
+impl Into<Option<Def>> for EnumData {
+    fn into(self) -> Option<Def> {
+        match self.visibility {
             Visibility::Public => Some(Def {
                 kind: DefKind::Enum,
-                id: From::from(data.id),
-                span: data.span,
-                name: data.name,
-                qualname: data.qualname,
-                value: data.value,
+                id: id_from_def_id(self.id),
+                span: self.span,
+                name: self.name,
+                qualname: self.qualname,
+                value: self.value,
                 parent: None,
-                children: data.variants.into_iter().map(|id| From::from(id)).collect(),
+                children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(),
                 decl_id: None,
-                docs: data.docs,
-                sig: Some(From::from(data.sig)),
+                docs: self.docs,
+                sig: Some(self.sig.into()),
+                attributes: vec![],
             }),
             _ => None,
         }
     }
 }
 
-impl From<TupleVariantData> for Option<Def> {
-    fn from(data: TupleVariantData) -> Option<Def> {
+impl Into<Option<Def>> for TupleVariantData {
+    fn into(self) -> Option<Def> {
         Some(Def {
             kind: DefKind::Tuple,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
-            parent: data.parent.map(|id| From::from(id)),
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: self.parent.map(|id| id_from_def_id(id)),
             children: vec![],
             decl_id: None,
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: vec![],
         })
     }
 }
-impl From<StructVariantData> for Option<Def> {
-    fn from(data: StructVariantData) -> Option<Def> {
+impl Into<Option<Def>> for StructVariantData {
+    fn into(self) -> Option<Def> {
         Some(Def {
             kind: DefKind::Struct,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
-            parent: data.parent.map(|id| From::from(id)),
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: self.parent.map(|id| id_from_def_id(id)),
             children: vec![],
             decl_id: None,
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: vec![],
         })
     }
 }
-impl From<StructData> for Option<Def> {
-    fn from(data: StructData) -> Option<Def> {
-        match data.visibility {
+impl Into<Option<Def>> for StructData {
+    fn into(self) -> Option<Def> {
+        match self.visibility {
             Visibility::Public => Some(Def {
             kind: DefKind::Struct,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
             parent: None,
-            children: data.fields.into_iter().map(|id| From::from(id)).collect(),
+            children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(),
             decl_id: None,
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: vec![],
         }),
             _ => None,
         }
     }
 }
-impl From<TraitData> for Option<Def> {
-    fn from(data: TraitData) -> Option<Def> {
-        match data.visibility {
+impl Into<Option<Def>> for TraitData {
+    fn into(self) -> Option<Def> {
+        match self.visibility {
             Visibility::Public => Some(Def {
                 kind: DefKind::Trait,
-                id: From::from(data.id),
-                span: data.span,
-                name: data.name,
-                qualname: data.qualname,
-                value: data.value,
-                children: data.items.into_iter().map(|id| From::from(id)).collect(),
+                id: id_from_def_id(self.id),
+                span: self.span,
+                name: self.name,
+                qualname: self.qualname,
+                value: self.value,
+                children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
                 parent: None,
                 decl_id: None,
-                docs: data.docs,
-                sig: Some(From::from(data.sig)),
+                docs: self.docs,
+                sig: Some(self.sig.into()),
+                attributes: vec![],
             }),
             _ => None,
         }
     }
 }
-impl From<FunctionData> for Option<Def> {
-    fn from(data: FunctionData) -> Option<Def> {
-        match data.visibility {
+impl Into<Option<Def>> for FunctionData {
+    fn into(self) -> Option<Def> {
+        match self.visibility {
             Visibility::Public => Some(Def {
                 kind: DefKind::Function,
-                id: From::from(data.id),
-                span: data.span,
-                name: data.name,
-                qualname: data.qualname,
-                value: data.value,
+                id: id_from_def_id(self.id),
+                span: self.span,
+                name: self.name,
+                qualname: self.qualname,
+                value: self.value,
                 children: vec![],
-                parent: data.parent.map(|id| From::from(id)),
+                parent: self.parent.map(|id| id_from_def_id(id)),
                 decl_id: None,
-                docs: data.docs,
-                sig: Some(From::from(data.sig)),
+                docs: self.docs,
+                sig: Some(self.sig.into()),
+                attributes: vec![],
             }),
             _ => None,
         }
     }
 }
-impl From<MethodData> for Option<Def> {
-    fn from(data: MethodData) -> Option<Def> {
-        match data.visibility {
+impl Into<Option<Def>> for MethodData {
+    fn into(self) -> Option<Def> {
+        match self.visibility {
             Visibility::Public => Some(Def {
                 kind: DefKind::Method,
-                id: From::from(data.id),
-                span: data.span,
-                name: data.name,
-                qualname: data.qualname,
-                value: data.value,
+                id: id_from_def_id(self.id),
+                span: self.span,
+                name: self.name,
+                qualname: self.qualname,
+                value: self.value,
                 children: vec![],
-                parent: data.parent.map(|id| From::from(id)),
-                decl_id: data.decl_id.map(|id| From::from(id)),
-                docs: data.docs,
-                sig: Some(From::from(data.sig)),
+                parent: self.parent.map(|id| id_from_def_id(id)),
+                decl_id: self.decl_id.map(|id| id_from_def_id(id)),
+                docs: self.docs,
+                sig: Some(self.sig.into()),
+                attributes: vec![],
             }),
             _ => None,
         }
     }
 }
-impl From<MacroData> for Option<Def> {
-    fn from(data: MacroData) -> Option<Def> {
+impl Into<Option<Def>> for MacroData {
+    fn into(self) -> Option<Def> {
         Some(Def {
             kind: DefKind::Macro,
-            id: From::from(null_def_id()),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
+            id: id_from_def_id(null_def_id()),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
             value: String::new(),
             children: vec![],
             parent: None,
             decl_id: None,
-            docs: data.docs,
+            docs: self.docs,
             sig: None,
+            attributes: vec![],
         })
     }
 }
-impl From<ModData> for Option<Def> {
-    fn from(data:ModData) -> Option<Def> {
-        match data.visibility {
+impl Into<Option<Def>> for ModData {
+    fn into(self) -> Option<Def> {
+        match self.visibility {
             Visibility::Public => Some(Def {
                 kind: DefKind::Mod,
-                id: From::from(data.id),
-                span: data.span,
-                name: data.name,
-                qualname: data.qualname,
-                value: data.filename,
-                children: data.items.into_iter().map(|id| From::from(id)).collect(),
+                id: id_from_def_id(self.id),
+                span: self.span,
+                name: self.name,
+                qualname: self.qualname,
+                value: self.filename,
+                children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
                 parent: None,
                 decl_id: None,
-                docs: data.docs,
-                sig: Some(From::from(data.sig)),
+                docs: self.docs,
+                sig: Some(self.sig.into()),
+                attributes: vec![],
             }),
             _ => None,
         }
     }
 }
-impl From<TypeDefData> for Option<Def> {
-    fn from(data: TypeDefData) -> Option<Def> {
-        match data.visibility {
+impl Into<Option<Def>> for TypeDefData {
+    fn into(self) -> Option<Def> {
+        match self.visibility {
             Visibility::Public => Some(Def {
                 kind: DefKind::Type,
-                id: From::from(data.id),
-                span: data.span,
-                name: data.name,
-                qualname: data.qualname,
-                value: data.value,
+                id: id_from_def_id(self.id),
+                span: self.span,
+                name: self.name,
+                qualname: self.qualname,
+                value: self.value,
                 children: vec![],
-                parent: data.parent.map(|id| From::from(id)),
+                parent: self.parent.map(|id| id_from_def_id(id)),
                 decl_id: None,
                 docs: String::new(),
-                sig: data.sig.map(|s| From::from(s)),
+                sig: self.sig.map(|s| s.into()),
+                attributes: vec![],
             }),
             _ => None,
         }
     }
 }
 
-impl From<VariableData> for Option<Def> {
-    fn from(data: VariableData) -> Option<Def> {
-        match data.visibility {
+impl Into<Option<Def>> for VariableData {
+    fn into(self) -> Option<Def> {
+        match self.visibility {
             Visibility::Public => Some(Def {
-                kind: match data.kind {
+                kind: match self.kind {
                     VariableKind::Static => DefKind::Static,
                     VariableKind::Const => DefKind::Const,
                     VariableKind::Local => { return None }
                     VariableKind::Field => DefKind::Field,
                 },
-                id: From::from(data.id),
-                span: data.span,
-                name: data.name,
-                qualname: data.qualname,
-                value: data.value,
+                id: id_from_def_id(self.id),
+                span: self.span,
+                name: self.name,
+                qualname: self.qualname,
+                value: self.value,
                 children: vec![],
-                parent: data.parent.map(|id| From::from(id)),
+                parent: self.parent.map(|id| id_from_def_id(id)),
                 decl_id: None,
-                docs: data.docs,
-                sig: data.sig.map(|s| From::from(s)),
+                docs: self.docs,
+                sig: self.sig.map(|s| s.into()),
+                attributes: vec![],
             }),
             _ => None,
         }
     }
 }
-
-#[derive(Debug, RustcEncodable)]
-struct Relation {
-    span: SpanData,
-    kind: RelationKind,
-    from: Id,
-    to: Id,
-}
-
-#[derive(Debug, RustcEncodable)]
-enum RelationKind {
-    Impl,
-    SuperTrait,
-}
-
-impl From<ImplData> for Relation {
-    fn from(data: ImplData) -> Relation {
-        Relation {
-            span: data.span,
-            kind: RelationKind::Impl,
-            from: From::from(data.self_ref.unwrap_or(null_def_id())),
-            to: From::from(data.trait_ref.unwrap_or(null_def_id())),
-        }
-    }
-}
-
-impl From<InheritanceData> for Relation {
-    fn from(data: InheritanceData) -> Relation {
-        Relation {
-            span: data.span,
-            kind: RelationKind::SuperTrait,
-            from: From::from(data.base_id),
-            to: From::from(data.deriv_id),
-        }
-    }
-}
-
-#[derive(Debug, RustcEncodable)]
-pub struct JsonSignature {
-    span: SpanData,
-    text: String,
-    ident_start: usize,
-    ident_end: usize,
-    defs: Vec<JsonSigElement>,
-    refs: Vec<JsonSigElement>,
-}
-
-impl From<Signature> for JsonSignature {
-    fn from(data: Signature) -> JsonSignature {
-        JsonSignature {
-            span: data.span,
-            text: data.text,
-            ident_start: data.ident_start,
-            ident_end: data.ident_end,
-            defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
-            refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
-        }
-    }
-}
-
-#[derive(Debug, RustcEncodable)]
-pub struct JsonSigElement {
-    id: Id,
-    start: usize,
-    end: usize,
-}
-
-impl From<SigElement> for JsonSigElement {
-    fn from(data: SigElement) -> JsonSigElement {
-        JsonSigElement {
-            id: From::from(data.id),
-            start: data.start,
-            end: data.end,
-        }
-    }
-}
index 1b72489f83c67da2d611710b757001966994c3f5..acc877d3947758fb20a222e51c2f6a896fe5c3e4 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc_serialize::json::as_json;
 
+use rls_data::{self, Id, Analysis, Import, ImportKind, Def, DefKind, Ref, RefKind, MacroRef,
+               Relation, RelationKind, Signature, SigElement, CratePreludeData};
+use rls_span::{Column, Row};
+
+use external_data;
 use external_data::*;
-use data::{VariableKind, SigElement};
+use data::{self, VariableKind};
 use dump::Dump;
-use super::Format;
 
 pub struct JsonDumper<'b, W: Write + 'b> {
     output: &'b mut W,
@@ -40,7 +44,7 @@ fn drop(&mut self) {
 macro_rules! impl_fn {
     ($fn_name: ident, $data_type: ident, $bucket: ident) => {
         fn $fn_name(&mut self, data: $data_type) {
-            self.result.$bucket.push(From::from(data));
+            self.result.$bucket.push(data.into());
         }
     }
 }
@@ -75,21 +79,22 @@ fn crate_prelude(&mut self, data: CratePreludeData) {
     impl_fn!(macro_use, MacroUseData, macro_refs);
 
     fn mod_data(&mut self, data: ModData) {
-        let id: Id = From::from(data.id);
+        let id: Id = id_from_def_id(data.id);
         let mut def = Def {
             kind: DefKind::Mod,
             id: id,
-            span: data.span,
+            span: data.span.into(),
             name: data.name,
             qualname: data.qualname,
             value: data.filename,
-            children: data.items.into_iter().map(|id| From::from(id)).collect(),
+            parent: None,
+            children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(),
             decl_id: None,
             docs: data.docs,
-            sig: Some(From::from(data.sig)),
-            attributes: data.attributes,
+            sig: Some(data.sig.into()),
+            attributes: data.attributes.into_iter().map(|a| a.into()).collect(),
         };
-        if def.span.file_name != def.value {
+        if def.span.file_name.to_str().unwrap() != def.value {
             // If the module is an out-of-line defintion, then we'll make the
             // defintion the first character in the module's file and turn the
             // the declaration into a reference to it.
@@ -99,14 +104,14 @@ fn mod_data(&mut self, data: ModData) {
                 ref_id: id,
             };
             self.result.refs.push(rf);
-            def.span = SpanData {
-                file_name: def.value.clone(),
+            def.span = rls_data::SpanData {
+                file_name: def.value.clone().into(),
                 byte_start: 0,
                 byte_end: 0,
-                line_start: 1,
-                line_end: 1,
-                column_start: 1,
-                column_end: 1,
+                line_start: Row::new_one_indexed(1),
+                line_end: Row::new_one_indexed(1),
+                column_start: Column::new_one_indexed(1),
+                column_end: Column::new_one_indexed(1),
             }
         }
 
@@ -115,11 +120,11 @@ fn mod_data(&mut self, data: ModData) {
 
     fn impl_data(&mut self, data: ImplData) {
         if data.self_ref.is_some() {
-            self.result.relations.push(From::from(data));
+            self.result.relations.push(data.into());
         }
     }
     fn inheritance(&mut self, data: InheritanceData) {
-        self.result.relations.push(From::from(data));
+        self.result.relations.push(data.into());
     }
 }
 
@@ -129,476 +134,342 @@ fn inheritance(&mut self, data: InheritanceData) {
 // method, but not the supplied method). In both cases, we are currently
 // ignoring it.
 
-#[derive(Debug, RustcEncodable)]
-struct Analysis {
-    kind: Format,
-    prelude: Option<CratePreludeData>,
-    imports: Vec<Import>,
-    defs: Vec<Def>,
-    refs: Vec<Ref>,
-    macro_refs: Vec<MacroRef>,
-    relations: Vec<Relation>,
-}
-
-impl Analysis {
-    fn new() -> Analysis {
-        Analysis {
-            kind: Format::Json,
-            prelude: None,
-            imports: vec![],
-            defs: vec![],
-            refs: vec![],
-            macro_refs: vec![],
-            relations: vec![],
-        }
-    }
-}
-
 // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
 // we use our own Id which is the same, but without the newtype.
-#[derive(Clone, Copy, Debug, RustcEncodable)]
-struct Id {
-    krate: u32,
-    index: u32,
-}
-
-impl From<DefId> for Id {
-    fn from(id: DefId) -> Id {
-        Id {
-            krate: id.krate.as_u32(),
-            index: id.index.as_u32(),
-        }
+pub fn id_from_def_id(id: DefId) -> Id {
+    Id {
+        krate: id.krate.as_u32(),
+        index: id.index.as_u32(),
     }
 }
 
-#[derive(Debug, RustcEncodable)]
-struct Import {
-    kind: ImportKind,
-    ref_id: Option<Id>,
-    span: SpanData,
-    name: String,
-    value: String,
-}
-
-#[derive(Debug, RustcEncodable)]
-enum ImportKind {
-    ExternCrate,
-    Use,
-    GlobUse,
-}
-
-impl From<ExternCrateData> for Import {
-    fn from(data: ExternCrateData) -> Import {
+impl Into<Import> for ExternCrateData {
+    fn into(self) -> Import {
         Import {
             kind: ImportKind::ExternCrate,
             ref_id: None,
-            span: data.span,
-            name: data.name,
+            span: self.span,
+            name: self.name,
             value: String::new(),
         }
     }
 }
-impl From<UseData> for Import {
-    fn from(data: UseData) -> Import {
+impl Into<Import> for UseData {
+    fn into(self) -> Import {
         Import {
             kind: ImportKind::Use,
-            ref_id: data.mod_id.map(|id| From::from(id)),
-            span: data.span,
-            name: data.name,
+            ref_id: self.mod_id.map(|id| id_from_def_id(id)),
+            span: self.span,
+            name: self.name,
             value: String::new(),
         }
     }
 }
-impl From<UseGlobData> for Import {
-    fn from(data: UseGlobData) -> Import {
+impl Into<Import> for UseGlobData {
+    fn into(self) -> Import {
         Import {
             kind: ImportKind::GlobUse,
             ref_id: None,
-            span: data.span,
+            span: self.span,
             name: "*".to_owned(),
-            value: data.names.join(", "),
+            value: self.names.join(", "),
         }
     }
 }
 
-#[derive(Debug, RustcEncodable)]
-struct Def {
-    kind: DefKind,
-    id: Id,
-    span: SpanData,
-    name: String,
-    qualname: String,
-    value: String,
-    children: Vec<Id>,
-    decl_id: Option<Id>,
-    docs: String,
-    sig: Option<JsonSignature>,
-    attributes: Vec<Attribute>,
-}
-
-#[derive(Debug, RustcEncodable)]
-enum DefKind {
-    // value = variant names
-    Enum,
-    // value = enum name + variant name + types
-    Tuple,
-    // value = [enum name +] name + fields
-    Struct,
-    // value = signature
-    Trait,
-    // value = type + generics
-    Function,
-    // value = type + generics
-    Method,
-    // No id, no value.
-    Macro,
-    // value = file_name
-    Mod,
-    // value = aliased type
-    Type,
-    // value = type and init expression (for all variable kinds).
-    Local,
-    Static,
-    Const,
-    Field,
-}
-
-impl From<EnumData> for Def {
-    fn from(data: EnumData) -> Def {
+impl Into<Def> for EnumData {
+    fn into(self) -> Def {
         Def {
             kind: DefKind::Enum,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
-            children: data.variants.into_iter().map(|id| From::from(id)).collect(),
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: None,
+            children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(),
             decl_id: None,
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
-            attributes: data.attributes,
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: self.attributes,
         }
     }
 }
 
-impl From<TupleVariantData> for Def {
-    fn from(data: TupleVariantData) -> Def {
+impl Into<Def> for TupleVariantData {
+    fn into(self) -> Def {
         Def {
             kind: DefKind::Tuple,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: None,
             children: vec![],
             decl_id: None,
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
-            attributes: data.attributes,
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: self.attributes,
         }
     }
 }
-impl From<StructVariantData> for Def {
-    fn from(data: StructVariantData) -> Def {
+impl Into<Def> for StructVariantData {
+    fn into(self) -> Def {
         Def {
             kind: DefKind::Struct,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: None,
             children: vec![],
             decl_id: None,
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
-            attributes: data.attributes,
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: self.attributes,
         }
     }
 }
-impl From<StructData> for Def {
-    fn from(data: StructData) -> Def {
+impl Into<Def> for StructData {
+    fn into(self) -> Def {
         Def {
             kind: DefKind::Struct,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
-            children: data.fields.into_iter().map(|id| From::from(id)).collect(),
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: None,
+            children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(),
             decl_id: None,
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
-            attributes: data.attributes,
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: self.attributes,
         }
     }
 }
-impl From<TraitData> for Def {
-    fn from(data: TraitData) -> Def {
+impl Into<Def> for TraitData {
+    fn into(self) -> Def {
         Def {
             kind: DefKind::Trait,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
-            children: data.items.into_iter().map(|id| From::from(id)).collect(),
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: None,
+            children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
             decl_id: None,
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
-            attributes: data.attributes,
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: self.attributes,
         }
     }
 }
-impl From<FunctionData> for Def {
-    fn from(data: FunctionData) -> Def {
+impl Into<Def> for FunctionData {
+    fn into(self) -> Def {
         Def {
             kind: DefKind::Function,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: None,
             children: vec![],
             decl_id: None,
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
-            attributes: data.attributes,
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: self.attributes,
         }
     }
 }
-impl From<MethodData> for Def {
-    fn from(data: MethodData) -> Def {
+impl Into<Def> for MethodData {
+    fn into(self) -> Def {
         Def {
             kind: DefKind::Method,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: None,
             children: vec![],
-            decl_id: data.decl_id.map(|id| From::from(id)),
-            docs: data.docs,
-            sig: Some(From::from(data.sig)),
-            attributes: data.attributes,
+            decl_id: self.decl_id.map(|id| id_from_def_id(id)),
+            docs: self.docs,
+            sig: Some(self.sig.into()),
+            attributes: self.attributes,
         }
     }
 }
-impl From<MacroData> for Def {
-    fn from(data: MacroData) -> Def {
+impl Into<Def> for MacroData {
+    fn into(self) -> Def {
         Def {
             kind: DefKind::Macro,
-            id: From::from(null_def_id()),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
+            id: id_from_def_id(null_def_id()),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
             value: String::new(),
+            parent: None,
             children: vec![],
             decl_id: None,
-            docs: data.docs,
+            docs: self.docs,
             sig: None,
             attributes: vec![],
         }
     }
 }
-impl From<TypeDefData> for Def {
-    fn from(data: TypeDefData) -> Def {
+impl Into<Def> for TypeDefData {
+    fn into(self) -> Def {
         Def {
             kind: DefKind::Type,
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.value,
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.value,
+            parent: None,
             children: vec![],
             decl_id: None,
             docs: String::new(),
-            sig: data.sig.map(|s| From::from(s)),
-            attributes: data.attributes,
+            sig: self.sig.map(|s| s.into()),
+            attributes: self.attributes,
         }
     }
 }
-impl From<VariableData> for Def {
-    fn from(data: VariableData) -> Def {
+impl Into<Def> for VariableData {
+    fn into(self) -> Def {
         Def {
-            kind: match data.kind {
+            kind: match self.kind {
                 VariableKind::Static => DefKind::Static,
                 VariableKind::Const => DefKind::Const,
                 VariableKind::Local => DefKind::Local,
                 VariableKind::Field => DefKind::Field,
             },
-            id: From::from(data.id),
-            span: data.span,
-            name: data.name,
-            qualname: data.qualname,
-            value: data.type_value,
+            id: id_from_def_id(self.id),
+            span: self.span,
+            name: self.name,
+            qualname: self.qualname,
+            value: self.type_value,
+            parent: None,
             children: vec![],
             decl_id: None,
-            docs: data.docs,
+            docs: self.docs,
             sig: None,
-            attributes: data.attributes,
+            attributes: self.attributes,
         }
     }
 }
 
-#[derive(Debug, RustcEncodable)]
-enum RefKind {
-    Function,
-    Mod,
-    Type,
-    Variable,
-}
-
-#[derive(Debug, RustcEncodable)]
-struct Ref {
-    kind: RefKind,
-    span: SpanData,
-    ref_id: Id,
-}
-
-impl From<FunctionRefData> for Ref {
-    fn from(data: FunctionRefData) -> Ref {
+impl Into<Ref> for FunctionRefData {
+    fn into(self) -> Ref {
         Ref {
             kind: RefKind::Function,
-            span: data.span,
-            ref_id: From::from(data.ref_id),
+            span: self.span,
+            ref_id: id_from_def_id(self.ref_id),
         }
     }
 }
-impl From<FunctionCallData> for Ref {
-    fn from(data: FunctionCallData) -> Ref {
+impl Into<Ref> for FunctionCallData {
+    fn into(self) -> Ref {
         Ref {
             kind: RefKind::Function,
-            span: data.span,
-            ref_id: From::from(data.ref_id),
+            span: self.span,
+            ref_id: id_from_def_id(self.ref_id),
         }
     }
 }
-impl From<MethodCallData> for Ref {
-    fn from(data: MethodCallData) -> Ref {
+impl Into<Ref> for MethodCallData {
+    fn into(self) -> Ref {
         Ref {
             kind: RefKind::Function,
-            span: data.span,
-            ref_id: From::from(data.ref_id.or(data.decl_id).unwrap_or(null_def_id())),
+            span: self.span,
+            ref_id: id_from_def_id(self.ref_id.or(self.decl_id).unwrap_or(null_def_id())),
         }
     }
 }
-impl From<ModRefData> for Ref {
-    fn from(data: ModRefData) -> Ref {
+impl Into<Ref> for ModRefData {
+    fn into(self) -> Ref {
         Ref {
             kind: RefKind::Mod,
-            span: data.span,
-            ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
+            span: self.span,
+            ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())),
         }
     }
 }
-impl From<TypeRefData> for Ref {
-    fn from(data: TypeRefData) -> Ref {
+impl Into<Ref> for TypeRefData {
+    fn into(self) -> Ref {
         Ref {
             kind: RefKind::Type,
-            span: data.span,
-            ref_id: From::from(data.ref_id.unwrap_or(null_def_id())),
+            span: self.span,
+            ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())),
         }
     }
 }
-impl From<VariableRefData> for Ref {
-    fn from(data: VariableRefData) -> Ref {
+impl Into<Ref> for VariableRefData {
+    fn into(self) -> Ref {
         Ref {
             kind: RefKind::Variable,
-            span: data.span,
-            ref_id: From::from(data.ref_id),
+            span: self.span,
+            ref_id: id_from_def_id(self.ref_id),
         }
     }
 }
 
-#[derive(Debug, RustcEncodable)]
-struct MacroRef {
-    span: SpanData,
-    qualname: String,
-    callee_span: SpanData,
-}
-
-impl From<MacroUseData> for MacroRef {
-    fn from(data: MacroUseData) -> MacroRef {
+impl Into<MacroRef> for MacroUseData {
+    fn into(self) -> MacroRef {
         MacroRef {
-            span: data.span,
-            qualname: data.qualname,
-            callee_span: data.callee_span,
+            span: self.span,
+            qualname: self.qualname,
+            callee_span: self.callee_span.into(),
         }
     }
 }
 
-#[derive(Debug, RustcEncodable)]
-struct Relation {
-    span: SpanData,
-    kind: RelationKind,
-    from: Id,
-    to: Id,
-}
-
-#[derive(Debug, RustcEncodable)]
-enum RelationKind {
-    Impl,
-    SuperTrait,
-}
-
-impl From<ImplData> for Relation {
-    fn from(data: ImplData) -> Relation {
+impl Into<Relation> for ImplData {
+    fn into(self) -> Relation {
         Relation {
-            span: data.span,
+            span: self.span,
             kind: RelationKind::Impl,
-            from: From::from(data.self_ref.unwrap_or(null_def_id())),
-            to: From::from(data.trait_ref.unwrap_or(null_def_id())),
+            from: id_from_def_id(self.self_ref.unwrap_or(null_def_id())),
+            to: id_from_def_id(self.trait_ref.unwrap_or(null_def_id())),
         }
     }
 }
 
-impl From<InheritanceData> for Relation {
-    fn from(data: InheritanceData) -> Relation {
+impl Into<Relation> for InheritanceData {
+    fn into(self) -> Relation {
         Relation {
-            span: data.span,
+            span: self.span,
             kind: RelationKind::SuperTrait,
-            from: From::from(data.base_id),
-            to: From::from(data.deriv_id),
+            from: id_from_def_id(self.base_id),
+            to: id_from_def_id(self.deriv_id),
         }
     }
 }
 
-#[derive(Debug, RustcEncodable)]
-pub struct JsonSignature {
-    span: SpanData,
-    text: String,
-    ident_start: usize,
-    ident_end: usize,
-    defs: Vec<JsonSigElement>,
-    refs: Vec<JsonSigElement>,
-}
-
-impl From<Signature> for JsonSignature {
-    fn from(data: Signature) -> JsonSignature {
-        JsonSignature {
-            span: data.span,
-            text: data.text,
-            ident_start: data.ident_start,
-            ident_end: data.ident_end,
-            defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
-            refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
+impl Into<Signature> for external_data::Signature {
+    fn into(self) -> Signature {
+        Signature {
+            span: self.span,
+            text: self.text,
+            ident_start: self.ident_start,
+            ident_end: self.ident_end,
+            defs: self.defs.into_iter().map(|s| s.into()).collect(),
+            refs: self.refs.into_iter().map(|s| s.into()).collect(),
         }
     }
 }
 
-#[derive(Debug, RustcEncodable)]
-pub struct JsonSigElement {
-    id: Id,
-    start: usize,
-    end: usize,
-}
-
-impl From<SigElement> for JsonSigElement {
-    fn from(data: SigElement) -> JsonSigElement {
-        JsonSigElement {
-            id: From::from(data.id),
-            start: data.start,
-            end: data.end,
+impl Into<SigElement> for data::SigElement {
+    fn into(self) -> SigElement {
+        SigElement {
+            id: id_from_def_id(self.id),
+            start: self.start,
+            end: self.end,
         }
     }
 }
index 581b23d52142d36ecd344d6f190faefda26b04c8..5e2b1df9d34f89451f28737760f2f4648dc487bc 100644 (file)
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
-extern crate serialize as rustc_serialize;
+extern crate rustc_serialize;
 extern crate syntax_pos;
 
+extern crate rls_data;
+extern crate rls_span;
+
 
 mod csv_dumper;
 mod json_api_dumper;
index 0bbe981f2f72c816bd50b38695693d25101450fb..27a19d211c2908ef4f5910aa1f4915859d28cede 100644 (file)
@@ -59,6 +59,7 @@ enum ArgKind {
 pub use self::attr_impl::ArgAttribute;
 
 #[allow(non_upper_case_globals)]
+#[allow(unused)]
 mod attr_impl {
     // The subset of llvm::Attribute needed for arguments, packed into a bitfield.
     bitflags! {
@@ -223,16 +224,6 @@ pub fn is_ignore(&self) -> bool {
         self.kind == ArgKind::Ignore
     }
 
-    /// Get the LLVM type for an lvalue of the original Rust type of
-    /// this argument/return, i.e. the result of `type_of::type_of`.
-    pub fn memory_ty(&self, ccx: &CrateContext) -> Type {
-        if self.original_ty == Type::i1(ccx) {
-            Type::i8(ccx)
-        } else {
-            self.original_ty
-        }
-    }
-
     /// Store a direct/indirect value described by this ArgType into a
     /// lvalue for the original Rust type of this argument/return.
     /// Can be used for both storing formal arguments into Rust variables
@@ -334,9 +325,19 @@ pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         fn_ty
     }
 
-    pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+    pub fn new_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 sig: ty::FnSig<'tcx>,
                                 extra_args: &[Ty<'tcx>]) -> FnType {
+        let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args);
+        // Don't pass the vtable, it's not an argument of the virtual fn.
+        fn_ty.args[1].ignore();
+        fn_ty.adjust_for_abi(ccx, sig);
+        fn_ty
+    }
+
+    fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                            sig: ty::FnSig<'tcx>,
+                            extra_args: &[Ty<'tcx>]) -> FnType {
         use self::Abi::*;
         let cconv = match ccx.sess().target.target.adjust_abi(sig.abi) {
             RustIntrinsic | PlatformIntrinsic |
@@ -532,9 +533,9 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
     }
 
-    pub fn adjust_for_abi<'a, 'tcx>(&mut self,
-                                    ccx: &CrateContext<'a, 'tcx>,
-                                    sig: ty::FnSig<'tcx>) {
+    fn adjust_for_abi<'a, 'tcx>(&mut self,
+                                ccx: &CrateContext<'a, 'tcx>,
+                                sig: ty::FnSig<'tcx>) {
         let abi = sig.abi;
         if abi == Abi::Unadjusted { return }
 
index 11d3fae823830318937767efd195601fa3f9643b..058f37f62dd82b70f87814f6ce567b2236d05c99 100644 (file)
@@ -363,28 +363,6 @@ fn load_discr(bcx: &Builder, ity: layout::Integer, ptr: ValueRef,
     }
 }
 
-/// Yield information about how to dispatch a case of the
-/// discriminant-like value returned by `trans_switch`.
-///
-/// This should ideally be less tightly tied to `_match`.
-pub fn trans_case<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, value: Disr) -> ValueRef {
-    let l = bcx.ccx.layout_of(t);
-    match *l {
-        layout::CEnum { discr, .. }
-        | layout::General { discr, .. }=> {
-            C_integral(Type::from_integer(bcx.ccx, discr), value.0, true)
-        }
-        layout::RawNullablePointer { .. } |
-        layout::StructWrappedNullablePointer { .. } => {
-            assert!(value == Disr(0) || value == Disr(1));
-            C_bool(bcx.ccx, value != Disr(0))
-        }
-        _ => {
-            bug!("{} does not have a discriminant. Represented as {:#?}", t, l);
-        }
-    }
-}
-
 /// Set the discriminant for a new value of the given case of the given
 /// representation.
 pub fn trans_set_discr<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, val: ValueRef, to: Disr) {
index efdd1b736f0e7ae77b8b14b69f1e5e89c53c414f..6bef31ccf64a423999d4f9bf664837eca1670da6 100644 (file)
@@ -17,6 +17,7 @@
 use syntax::ast;
 use context::CrateContext;
 
+
 /// Mark LLVM function to use provided inline heuristic.
 #[inline]
 pub fn inline(val: ValueRef, inline: InlineAttr) {
index bea3ca8df70e0babf243b0c40c210ddbe75bc4ae..005fb3533ab0b793510bdec9fde95630c2a46744 100644 (file)
@@ -11,6 +11,7 @@
 use context::SharedCrateContext;
 use monomorphize::Instance;
 use symbol_map::SymbolMap;
+use back::symbol_names::symbol_name;
 use util::nodemap::FxHashMap;
 use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
 use rustc::session::config;
@@ -106,7 +107,7 @@ pub fn compute_from<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
                 .exported_symbols(cnum)
                 .iter()
                 .map(|&def_id| {
-                    let name = Instance::mono(scx, def_id).symbol_name(scx);
+                    let name = symbol_name(Instance::mono(scx.tcx(), def_id), scx);
                     let export_level = if special_runtime_crate {
                         // We can probably do better here by just ensuring that
                         // it has hidden visibility rather than public
@@ -218,9 +219,9 @@ fn symbol_for_def_id<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         }
     }
 
-    let instance = Instance::mono(scx, def_id);
+    let instance = Instance::mono(scx.tcx(), def_id);
 
     symbol_map.get(TransItem::Fn(instance))
               .map(str::to_owned)
-              .unwrap_or_else(|| instance.symbol_name(scx))
+              .unwrap_or_else(|| symbol_name(instance, scx))
 }
index fe58bc8f5f28bde9bed02f7a2188ee2af45dddd6..518995dfedcc282fac84b41ada9f0ebb288837be 100644 (file)
@@ -168,105 +168,105 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
     format!("h{:016x}", hasher.finish())
 }
 
-impl<'a, 'tcx> Instance<'tcx> {
-    pub fn symbol_name(self, scx: &SharedCrateContext<'a, 'tcx>) -> String {
-        let Instance { def: def_id, substs } = self;
+pub fn symbol_name<'a, 'tcx>(instance: Instance<'tcx>,
+                             scx: &SharedCrateContext<'a, 'tcx>) -> String {
+    let def_id = instance.def_id();
+    let substs = instance.substs;
 
-        debug!("symbol_name(def_id={:?}, substs={:?})",
-               def_id, substs);
+    debug!("symbol_name(def_id={:?}, substs={:?})",
+           def_id, substs);
 
-        let node_id = scx.tcx().hir.as_local_node_id(def_id);
+    let node_id = scx.tcx().hir.as_local_node_id(def_id);
 
-        if let Some(id) = node_id {
-            if scx.sess().plugin_registrar_fn.get() == Some(id) {
-                let svh = &scx.link_meta().crate_hash;
-                let idx = def_id.index;
-                return scx.sess().generate_plugin_registrar_symbol(svh, idx);
-            }
-            if scx.sess().derive_registrar_fn.get() == Some(id) {
-                let svh = &scx.link_meta().crate_hash;
-                let idx = def_id.index;
-                return scx.sess().generate_derive_registrar_symbol(svh, idx);
-            }
+    if let Some(id) = node_id {
+        if scx.sess().plugin_registrar_fn.get() == Some(id) {
+            let svh = &scx.link_meta().crate_hash;
+            let idx = def_id.index;
+            return scx.sess().generate_plugin_registrar_symbol(svh, idx);
         }
-
-        // FIXME(eddyb) Precompute a custom symbol name based on attributes.
-        let attrs = scx.tcx().get_attrs(def_id);
-        let is_foreign = if let Some(id) = node_id {
-            match scx.tcx().hir.get(id) {
-                hir_map::NodeForeignItem(_) => true,
-                _ => false
-            }
-        } else {
-            scx.sess().cstore.is_foreign_item(def_id)
-        };
-
-        if let Some(name) = weak_lang_items::link_name(&attrs) {
-            return name.to_string();
+        if scx.sess().derive_registrar_fn.get() == Some(id) {
+            let svh = &scx.link_meta().crate_hash;
+            let idx = def_id.index;
+            return scx.sess().generate_derive_registrar_symbol(svh, idx);
         }
+    }
 
-        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 scx.tcx().item_name(def_id).as_str().to_string();
+    // FIXME(eddyb) Precompute a custom symbol name based on attributes.
+    let attrs = scx.tcx().get_attrs(def_id);
+    let is_foreign = if let Some(id) = node_id {
+        match scx.tcx().hir.get(id) {
+            hir_map::NodeForeignItem(_) => true,
+            _ => false
         }
+    } else {
+        scx.sess().cstore.is_foreign_item(def_id)
+    };
 
-        if let Some(name) = attr::find_export_name_attr(scx.sess().diagnostic(), &attrs) {
-            // Use provided name
+    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 scx.tcx().item_name(def_id).as_str().to_string();
+    }
 
-        if attr::contains_name(&attrs, "no_mangle") {
-            // Don't mangle
-            return scx.tcx().item_name(def_id).as_str().to_string();
-        }
+    if let Some(name) = attr::find_export_name_attr(scx.sess().diagnostic(), &attrs) {
+        // Use provided name
+        return name.to_string();
+    }
 
-        let def_path = scx.tcx().def_path(def_id);
-
-        // 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 = scx.tcx().def_key(ty_def_id);
-            match key.disambiguated_data.data {
-                DefPathData::TypeNs(_) |
-                DefPathData::ValueNs(_) => {
-                    instance_ty = scx.tcx().item_type(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);
-                    });
-                }
+    if attr::contains_name(&attrs, "no_mangle") {
+        // Don't mangle
+        return scx.tcx().item_name(def_id).as_str().to_string();
+    }
+
+    let def_path = scx.tcx().def_path(def_id);
+
+    // 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 = scx.tcx().def_key(ty_def_id);
+        match key.disambiguated_data.data {
+            DefPathData::TypeNs(_) |
+            DefPathData::ValueNs(_) => {
+                instance_ty = scx.tcx().item_type(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 = scx.tcx().erase_regions(&instance_ty);
+    // Erase regions because they may not be deterministic when hashed
+    // and should not matter anyhow.
+    let instance_ty = scx.tcx().erase_regions(&instance_ty);
 
-        let hash = get_symbol_hash(scx, &def_path, instance_ty, Some(substs));
+    let hash = get_symbol_hash(scx, &def_path, instance_ty, Some(substs));
 
-        let mut buffer = SymbolPathBuffer {
-            names: Vec::with_capacity(def_path.data.len())
-        };
+    let mut buffer = SymbolPathBuffer {
+        names: Vec::with_capacity(def_path.data.len())
+    };
 
-        item_path::with_forced_absolute_paths(|| {
-            scx.tcx().push_item_path(&mut buffer, def_id);
-        });
+    item_path::with_forced_absolute_paths(|| {
+        scx.tcx().push_item_path(&mut buffer, def_id);
+    });
 
-        mangle(buffer.names.into_iter(), &hash)
-    }
+    mangle(buffer.names.into_iter(), &hash)
 }
 
 struct SymbolPathBuffer {
index 1b43491e73c8f420e6efafcb5c308e46483ad2fa..6593b8e68d425fbd21a818bd87cb58b5c0348ce8 100644 (file)
 use back::symbol_export::{self, ExportedSymbols};
 use llvm::{Linkage, ValueRef, Vector, get_param};
 use llvm;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::hir::def_id::LOCAL_CRATE;
 use middle::lang_items::StartFnLangItem;
-use rustc::ty::subst::Substs;
-use rustc::mir::tcx::LvalueTy;
-use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::dep_graph::{AssertDepGraphSafe, DepNode, WorkProduct};
 use rustc::hir::map as hir_map;
 use rustc::util::common::time;
 use session::config::{self, NoDebugInfo};
 use rustc_incremental::IncrementalHashesMap;
 use session::{self, DataTypeKind, Session};
-use abi::{self, FnType};
+use abi;
 use mir::lvalue::LvalueRef;
-use adt;
 use attributes;
 use builder::Builder;
-use callee::{Callee};
+use callee;
 use common::{C_bool, C_bytes_in_context, C_i32, C_uint};
 use collector::{self, TransItemCollectionMode};
 use common::{C_struct_in_context, C_u64, C_undef};
 use common::CrateContext;
-use common::{fulfill_obligation};
 use common::{type_is_zero_size, val_ty};
 use common;
 use consts;
@@ -65,7 +59,7 @@
 use debuginfo;
 use declare;
 use machine;
-use machine::{llalign_of_min, llsize_of};
+use machine::llsize_of;
 use meth;
 use mir;
 use monomorphize::{self, Instance};
@@ -76,7 +70,6 @@
 use type_::Type;
 use type_of;
 use value::Value;
-use Disr;
 use util::nodemap::{NodeSet, FxHashMap, FxHashSet};
 
 use libc::c_uint;
@@ -84,7 +77,7 @@
 use std::rc::Rc;
 use std::str;
 use std::i32;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::Span;
 use syntax::attr;
 use rustc::hir;
 use rustc::ty::layout::{self, Layout};
@@ -317,25 +310,6 @@ pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
     }
 }
 
-pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx>,
-                                             source_ty: Ty<'tcx>,
-                                             target_ty: Ty<'tcx>)
-                                             -> CustomCoerceUnsized {
-    let trait_ref = ty::Binder(ty::TraitRef {
-        def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(),
-        substs: scx.tcx().mk_substs_trait(source_ty, &[target_ty])
-    });
-
-    match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
-        traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
-            scx.tcx().custom_coerce_unsized_kind(impl_def_id)
-        }
-        vtable => {
-            bug!("invalid CoerceUnsized vtable: {:?}", vtable);
-        }
-    }
-}
-
 pub fn cast_shift_expr_rhs(
     cx: &Builder, op: hir::BinOp_, lhs: ValueRef, rhs: ValueRef
 ) -> ValueRef {
@@ -429,7 +403,9 @@ pub fn load_ty<'a, 'tcx>(b: &Builder<'a, 'tcx>, ptr: ValueRef,
         // a char is a Unicode codepoint, and so takes values from 0
         // to 0x10FFFF inclusive only.
         b.load_range_assert(ptr, 0, 0x10FFFF + 1, llvm::False, alignment.to_align())
-    } else if (t.is_region_ptr() || t.is_box()) && !common::type_is_fat_ptr(ccx, t) {
+    } else if (t.is_region_ptr() || t.is_box() || t.is_fn())
+        && !common::type_is_fat_ptr(ccx, t)
+    {
         b.load_nonnull(ptr, alignment.to_align())
     } else {
         b.load(ptr, alignment.to_align())
@@ -569,11 +545,11 @@ pub fn memcpy_ty<'a, 'tcx>(
 }
 
 pub fn call_memset<'a, 'tcx>(b: &Builder<'a, 'tcx>,
-                               ptr: ValueRef,
-                               fill_byte: ValueRef,
-                               size: ValueRef,
-                               align: ValueRef,
-                               volatile: bool) -> ValueRef {
+                             ptr: ValueRef,
+                             fill_byte: ValueRef,
+                             size: ValueRef,
+                             align: ValueRef,
+                             volatile: bool) -> ValueRef {
     let ptr_width = &b.ccx.sess().target.target.target_pointer_width[..];
     let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
     let llintrinsicfn = b.ccx.get_intrinsic(&intrinsic_key);
@@ -585,7 +561,7 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance
     let _s = if ccx.sess().trans_stats() {
         let mut instance_name = String::new();
         DefPathBasedNames::new(ccx.tcx(), true, true)
-            .push_def_path(instance.def, &mut instance_name);
+            .push_def_path(instance.def_id(), &mut instance_name);
         Some(StatRecorder::new(ccx, instance_name))
     } else {
         None
@@ -596,7 +572,7 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance
     // release builds.
     info!("trans_instance({})", instance);
 
-    let fn_ty = common::def_ty(ccx.shared(), instance.def, instance.substs);
+    let fn_ty = common::instance_ty(ccx.shared(), &instance);
     let sig = common::ty_fn_sig(ccx, fn_ty);
     let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
 
@@ -611,76 +587,10 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance
         attributes::emit_uwtable(lldecl, true);
     }
 
-    let mir = ccx.tcx().item_mir(instance.def);
+    let mir = ccx.tcx().instance_mir(instance.def);
     mir::trans_mir(ccx, lldecl, &mir, instance, sig);
 }
 
-pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                 def_id: DefId,
-                                 substs: &'tcx Substs<'tcx>,
-                                 disr: Disr,
-                                 llfn: ValueRef) {
-    attributes::inline(llfn, attributes::InlineAttr::Hint);
-    attributes::set_frame_pointer_elimination(ccx, llfn);
-
-    let ctor_ty = common::def_ty(ccx.shared(), def_id, substs);
-    let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&ctor_ty.fn_sig());
-    let fn_ty = FnType::new(ccx, sig, &[]);
-
-    let bcx = Builder::new_block(ccx, llfn, "entry-block");
-    if !fn_ty.ret.is_ignore() {
-        // But if there are no nested returns, we skip the indirection
-        // and have a single retslot
-        let dest = if fn_ty.ret.is_indirect() {
-            get_param(llfn, 0)
-        } else {
-            // We create an alloca to hold a pointer of type `ret.original_ty`
-            // which will hold the pointer to the right alloca which has the
-            // final ret value
-            bcx.alloca(fn_ty.ret.memory_ty(ccx), "sret_slot")
-        };
-        // Can return unsized value
-        let mut dest_val = LvalueRef::new_sized_ty(dest, sig.output(), Alignment::AbiAligned);
-        dest_val.ty = LvalueTy::Downcast {
-            adt_def: sig.output().ty_adt_def().unwrap(),
-            substs: substs,
-            variant_index: disr.0 as usize,
-        };
-        let mut llarg_idx = fn_ty.ret.is_indirect() as usize;
-        let mut arg_idx = 0;
-        for (i, arg_ty) in sig.inputs().iter().enumerate() {
-            let (lldestptr, _) = dest_val.trans_field_ptr(&bcx, i);
-            let arg = &fn_ty.args[arg_idx];
-            arg_idx += 1;
-            if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
-                let meta = &fn_ty.args[arg_idx];
-                arg_idx += 1;
-                arg.store_fn_arg(&bcx, &mut llarg_idx, get_dataptr(&bcx, lldestptr));
-                meta.store_fn_arg(&bcx, &mut llarg_idx, get_meta(&bcx, lldestptr));
-            } else {
-                arg.store_fn_arg(&bcx, &mut llarg_idx, lldestptr);
-            }
-        }
-        adt::trans_set_discr(&bcx, sig.output(), dest, disr);
-
-        if fn_ty.ret.is_indirect() {
-            bcx.ret_void();
-            return;
-        }
-
-        if let Some(cast_ty) = fn_ty.ret.cast {
-            bcx.ret(bcx.load(
-                bcx.pointercast(dest, cast_ty.ptr_to()),
-                Some(llalign_of_min(ccx, fn_ty.ret.ty))
-            ));
-        } else {
-            bcx.ret(bcx.load(dest, None))
-        }
-    } else {
-        bcx.ret_void();
-    }
-}
-
 pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
     // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
     // applicable to variable declarations and may not really make sense for
@@ -721,7 +631,7 @@ pub fn set_link_section(ccx: &CrateContext,
 }
 
 /// Create the `main` function which will initialise the rust runtime and call
-/// users main function.
+/// users main function.
 pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
     let (main_def_id, span) = match *ccx.sess().entry_fn.borrow() {
         Some((id, span)) => {
@@ -738,7 +648,7 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
         ccx.tcx().sess.span_fatal(span, "compilation successful");
     }
 
-    let instance = Instance::mono(ccx.shared(), main_def_id);
+    let instance = Instance::mono(ccx.tcx(), main_def_id);
 
     if !ccx.codegen_unit().contains_item(&TransItem::Fn(instance)) {
         // We want to create the wrapper in the same codegen unit as Rust's main
@@ -746,7 +656,7 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
         return;
     }
 
-    let main_llfn = Callee::def(ccx, main_def_id, instance.substs).reify(ccx);
+    let main_llfn = callee::get_fn(ccx, instance);
 
     let et = ccx.sess().entry_type.get().unwrap();
     match et {
@@ -780,8 +690,8 @@ fn create_entry_fn(ccx: &CrateContext,
 
         let (start_fn, args) = if use_start_lang_item {
             let start_def_id = ccx.tcx().require_lang_item(StartFnLangItem);
-            let empty_substs = ccx.tcx().intern_substs(&[]);
-            let start_fn = Callee::def(ccx, start_def_id, empty_substs).reify(ccx);
+            let start_instance = Instance::mono(ccx.tcx(), start_def_id);
+            let start_fn = callee::get_fn(ccx, start_instance);
             (start_fn, vec![bld.pointercast(rust_main, Type::i8p(ccx).ptr_to()), get_param(llfn, 0),
                 get_param(llfn, 1)])
         } else {
index 762aaf1ce1d1b8734cf11fa766850bc1c21e4eb3..aefee51191ac4e3804efe66880ab7d32ee1ce5ac 100644 (file)
 //! and methods are represented as just a fn ptr and not a full
 //! closure.
 
-pub use self::CalleeData::*;
-
-use llvm::{self, ValueRef, get_params};
+use llvm::{self, ValueRef};
 use rustc::hir::def_id::DefId;
-use rustc::ty::subst::{Substs, Subst};
-use rustc::traits;
-use abi::{Abi, FnType};
+use rustc::ty::subst::Substs;
 use attributes;
-use base;
-use builder::Builder;
 use common::{self, CrateContext};
-use cleanup::CleanupScope;
-use mir::lvalue::LvalueRef;
+use monomorphize;
 use consts;
-use common::def_ty;
 use declare;
-use value::Value;
-use meth;
 use monomorphize::Instance;
 use trans_item::TransItem;
 use type_of;
-use Disr;
-use rustc::ty::{self, Ty, TypeFoldable};
-use rustc::hir;
-use std::iter;
-
-use syntax_pos::DUMMY_SP;
-
-use mir::lvalue::Alignment;
-
-#[derive(Debug)]
-pub enum CalleeData {
-    /// Constructor for enum variant/tuple-like-struct.
-    NamedTupleConstructor(Disr),
-
-    /// Function pointer.
-    Fn(ValueRef),
-
-    Intrinsic,
-
-    /// Trait object found in the vtable at that index.
-    Virtual(usize)
-}
-
-#[derive(Debug)]
-pub struct Callee<'tcx> {
-    pub data: CalleeData,
-    pub ty: Ty<'tcx>
-}
-
-impl<'tcx> Callee<'tcx> {
-    /// Function pointer.
-    pub fn ptr(llfn: ValueRef, ty: Ty<'tcx>) -> Callee<'tcx> {
-        Callee {
-            data: Fn(llfn),
-            ty: ty
-        }
-    }
-
-    /// Function or method definition.
-    pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, substs: &'tcx Substs<'tcx>)
-                   -> Callee<'tcx> {
-        let tcx = ccx.tcx();
-
-        if let Some(trait_id) = tcx.trait_of_item(def_id) {
-            return Callee::trait_method(ccx, trait_id, def_id, substs);
-        }
-
-        let fn_ty = def_ty(ccx.shared(), def_id, substs);
-        if let ty::TyFnDef(.., f) = fn_ty.sty {
-            if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
-                return Callee {
-                    data: Intrinsic,
-                    ty: fn_ty
-                };
-            }
-        }
-
-        // FIXME(eddyb) Detect ADT constructors more efficiently.
-        if let Some(adt_def) = fn_ty.fn_ret().skip_binder().ty_adt_def() {
-            if let Some(i) = adt_def.variants.iter().position(|v| def_id == v.did) {
-                return Callee {
-                    data: NamedTupleConstructor(Disr::for_variant(tcx, adt_def, i)),
-                    ty: fn_ty
-                };
-            }
-        }
-
-        let (llfn, ty) = get_fn(ccx, def_id, substs);
-        Callee::ptr(llfn, ty)
-    }
-
-    /// Trait method, which has to be resolved to an impl method.
-    pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
-                            trait_id: DefId,
-                            def_id: DefId,
-                            substs: &'tcx Substs<'tcx>)
-                            -> Callee<'tcx> {
-        let tcx = ccx.tcx();
-
-        let trait_ref = ty::TraitRef::from_method(tcx, trait_id, substs);
-        let trait_ref = tcx.normalize_associated_type(&ty::Binder(trait_ref));
-        match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) {
-            traits::VtableImpl(vtable_impl) => {
-                let name = tcx.item_name(def_id);
-                let (def_id, substs) = traits::find_method(tcx, name, substs, &vtable_impl);
-
-                // Translate the function, bypassing Callee::def.
-                // That is because default methods have the same ID as the
-                // trait method used to look up the impl method that ended
-                // up here, so calling Callee::def would infinitely recurse.
-                let (llfn, ty) = get_fn(ccx, def_id, substs);
-                Callee::ptr(llfn, ty)
-            }
-            traits::VtableClosure(vtable_closure) => {
-                // The substitutions should have no type parameters remaining
-                // after passing through fulfill_obligation
-                let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
-                let instance = Instance::new(def_id, substs);
-                let llfn = trans_closure_method(
-                    ccx,
-                    vtable_closure.closure_def_id,
-                    vtable_closure.substs,
-                    instance,
-                    trait_closure_kind);
-
-                let method_ty = def_ty(ccx.shared(), def_id, substs);
-                Callee::ptr(llfn, method_ty)
-            }
-            traits::VtableFnPointer(vtable_fn_pointer) => {
-                let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
-                let instance = Instance::new(def_id, substs);
-                let llfn = trans_fn_pointer_shim(ccx, instance,
-                                                 trait_closure_kind,
-                                                 vtable_fn_pointer.fn_ty);
-
-                let method_ty = def_ty(ccx.shared(), def_id, substs);
-                Callee::ptr(llfn, method_ty)
-            }
-            traits::VtableObject(ref data) => {
-                Callee {
-                    data: Virtual(tcx.get_vtable_index_of_object_method(data, def_id)),
-                    ty: def_ty(ccx.shared(), def_id, substs)
-                }
-            }
-            vtable => {
-                bug!("resolved vtable bad vtable {:?} in trans", vtable);
-            }
-        }
-    }
-
-    /// Get the abi::FnType for a direct call. Mainly deals with the fact
-    /// that a Virtual call doesn't take the vtable, like its shim does.
-    /// The extra argument types are for variadic (extern "C") functions.
-    pub fn direct_fn_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
-                              extra_args: &[Ty<'tcx>]) -> FnType {
-        let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&self.ty.fn_sig());
-        let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args);
-        if let Virtual(_) = self.data {
-            // Don't pass the vtable, it's not an argument of the virtual fn.
-            fn_ty.args[1].ignore();
-        }
-        fn_ty.adjust_for_abi(ccx, sig);
-        fn_ty
-    }
-
-    /// Turn the callee into a function pointer.
-    pub fn reify<'a>(self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
-        match self.data {
-            Fn(llfn) => llfn,
-            Virtual(_) => meth::trans_object_shim(ccx, self),
-            NamedTupleConstructor(disr) => match self.ty.sty {
-                ty::TyFnDef(def_id, substs, _) => {
-                    let instance = Instance::new(def_id, substs);
-                    if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
-                        return llfn;
-                    }
-
-                    let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
-                                                              TransItem::Fn(instance));
-                    assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
-                    let lldecl = declare::define_internal_fn(ccx, &sym, self.ty);
-                    base::trans_ctor_shim(ccx, def_id, substs, disr, lldecl);
-                    ccx.instances().borrow_mut().insert(instance, lldecl);
-
-                    lldecl
-                }
-                _ => bug!("expected fn item type, found {}", self.ty)
-            },
-            Intrinsic => bug!("intrinsic {} getting reified", self.ty)
-        }
-    }
-}
-
-fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
-                                  def_id: DefId,
-                                  substs: ty::ClosureSubsts<'tcx>,
-                                  method_instance: Instance<'tcx>,
-                                  trait_closure_kind: ty::ClosureKind)
-                                  -> ValueRef
-{
-    // If this is a closure, redirect to it.
-    let (llfn, _) = get_fn(ccx, def_id, substs.substs);
-
-    // If the closure is a Fn closure, but a FnOnce is needed (etc),
-    // then adapt the self type
-    let llfn_closure_kind = ccx.tcx().closure_kind(def_id);
-
-    debug!("trans_closure_adapter_shim(llfn_closure_kind={:?}, \
-           trait_closure_kind={:?}, llfn={:?})",
-           llfn_closure_kind, trait_closure_kind, Value(llfn));
-
-    match needs_fn_once_adapter_shim(llfn_closure_kind, trait_closure_kind) {
-        Ok(true) => trans_fn_once_adapter_shim(ccx,
-                                               def_id,
-                                               substs,
-                                               method_instance,
-                                               llfn),
-        Ok(false) => llfn,
-        Err(()) => {
-            bug!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
-                 llfn_closure_kind,
-                 trait_closure_kind);
-        }
-    }
-}
-
-pub fn needs_fn_once_adapter_shim(actual_closure_kind: ty::ClosureKind,
-                                  trait_closure_kind: ty::ClosureKind)
-                                  -> Result<bool, ()>
-{
-    match (actual_closure_kind, trait_closure_kind) {
-        (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
-        (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
-        (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
-            // No adapter needed.
-           Ok(false)
-        }
-        (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
-            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
-            // `fn(&mut self, ...)`. In fact, at trans time, these are
-            // basically the same thing, so we can just return llfn.
-            Ok(false)
-        }
-        (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
-        (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
-            // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
-            // self, ...)`.  We want a `fn(self, ...)`. We can produce
-            // this by doing something like:
-            //
-            //     fn call_once(self, ...) { call_mut(&self, ...) }
-            //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
-            //
-            // These are both the same at trans time.
-            Ok(true)
-        }
-        _ => Err(()),
-    }
-}
-
-fn trans_fn_once_adapter_shim<'a, 'tcx>(
-    ccx: &'a CrateContext<'a, 'tcx>,
-    def_id: DefId,
-    substs: ty::ClosureSubsts<'tcx>,
-    method_instance: Instance<'tcx>,
-    llreffn: ValueRef)
-    -> ValueRef
-{
-    if let Some(&llfn) = ccx.instances().borrow().get(&method_instance) {
-        return llfn;
-    }
-
-    debug!("trans_fn_once_adapter_shim(def_id={:?}, substs={:?}, llreffn={:?})",
-           def_id, substs, Value(llreffn));
-
-    let tcx = ccx.tcx();
-
-    // Find a version of the closure type. Substitute static for the
-    // region since it doesn't really matter.
-    let closure_ty = tcx.mk_closure_from_closure_substs(def_id, substs);
-    let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), closure_ty);
-
-    // Make a version with the type of by-ref closure.
-    let sig = tcx.closure_type(def_id).subst(tcx, substs.substs);
-    let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
-    assert_eq!(sig.abi, Abi::RustCall);
-    let llref_fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
-        iter::once(ref_closure_ty).chain(sig.inputs().iter().cloned()),
-        sig.output(),
-        sig.variadic,
-        sig.unsafety,
-        Abi::RustCall
-    )));
-    debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
-           llref_fn_ty);
-
-
-    // Make a version of the closure type with the same arguments, but
-    // with argument #0 being by value.
-    let sig = tcx.mk_fn_sig(
-        iter::once(closure_ty).chain(sig.inputs().iter().cloned()),
-        sig.output(),
-        sig.variadic,
-        sig.unsafety,
-        Abi::RustCall
-    );
-
-    let fn_ty = FnType::new(ccx, sig, &[]);
-    let llonce_fn_ty = tcx.mk_fn_ptr(ty::Binder(sig));
-
-    // Create the by-value helper.
-    let function_name = method_instance.symbol_name(ccx.shared());
-    let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty);
-    attributes::set_frame_pointer_elimination(ccx, lloncefn);
-
-    let orig_fn_ty = fn_ty;
-    let mut bcx = Builder::new_block(ccx, lloncefn, "entry-block");
-
-    let callee = Callee {
-        data: Fn(llreffn),
-        ty: llref_fn_ty
-    };
-
-    // the first argument (`self`) will be the (by value) closure env.
-
-    let mut llargs = get_params(lloncefn);
-    let fn_ret = callee.ty.fn_ret();
-    let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
-    let self_idx = fn_ty.ret.is_indirect() as usize;
-    let env_arg = &orig_fn_ty.args[0];
-    let env = if env_arg.is_indirect() {
-        LvalueRef::new_sized_ty(llargs[self_idx], closure_ty, Alignment::AbiAligned)
-    } else {
-        let scratch = LvalueRef::alloca(&bcx, closure_ty, "self");
-        let mut llarg_idx = self_idx;
-        env_arg.store_fn_arg(&bcx, &mut llarg_idx, scratch.llval);
-        scratch
-    };
-
-    debug!("trans_fn_once_adapter_shim: env={:?}", env);
-    // Adjust llargs such that llargs[self_idx..] has the call arguments.
-    // For zero-sized closures that means sneaking in a new argument.
-    if env_arg.is_ignore() {
-        llargs.insert(self_idx, env.llval);
-    } else {
-        llargs[self_idx] = env.llval;
-    }
-
-    // Call the by-ref closure body with `self` in a cleanup scope,
-    // to drop `self` when the body returns, or in case it unwinds.
-    let self_scope = CleanupScope::schedule_drop_mem(&bcx, env);
-
-    let llfn = callee.reify(bcx.ccx);
-    let llret;
-    if let Some(landing_pad) = self_scope.landing_pad {
-        let normal_bcx = bcx.build_sibling_block("normal-return");
-        llret = bcx.invoke(llfn, &llargs[..], normal_bcx.llbb(), landing_pad, None);
-        bcx = normal_bcx;
-    } else {
-        llret = bcx.call(llfn, &llargs[..], None);
-    }
-    fn_ty.apply_attrs_callsite(llret);
-
-    if fn_ret.0.is_never() {
-        bcx.unreachable();
-    } else {
-        self_scope.trans(&bcx);
-
-        if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
-            bcx.ret_void();
-        } else {
-            bcx.ret(llret);
-        }
-    }
-
-    ccx.instances().borrow_mut().insert(method_instance, lloncefn);
-
-    lloncefn
-}
-
-/// Translates an adapter that implements the `Fn` trait for a fn
-/// pointer. This is basically the equivalent of something like:
-///
-/// ```
-/// impl<'a> Fn(&'a int) -> &'a int for fn(&int) -> &int {
-///     extern "rust-abi" fn call(&self, args: (&'a int,)) -> &'a int {
-///         (*self)(args.0)
-///     }
-/// }
-/// ```
-///
-/// but for the bare function type given.
-fn trans_fn_pointer_shim<'a, 'tcx>(
-    ccx: &'a CrateContext<'a, 'tcx>,
-    method_instance: Instance<'tcx>,
-    closure_kind: ty::ClosureKind,
-    bare_fn_ty: Ty<'tcx>)
-    -> ValueRef
-{
-    let tcx = ccx.tcx();
-
-    // Normalize the type for better caching.
-    let bare_fn_ty = tcx.normalize_associated_type(&bare_fn_ty);
-
-    // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
-    let is_by_ref = match closure_kind {
-        ty::ClosureKind::Fn | ty::ClosureKind::FnMut => true,
-        ty::ClosureKind::FnOnce => false,
-    };
-
-    let llfnpointer = match bare_fn_ty.sty {
-        ty::TyFnDef(def_id, substs, _) => {
-            // Function definitions have to be turned into a pointer.
-            let llfn = Callee::def(ccx, def_id, substs).reify(ccx);
-            if !is_by_ref {
-                // A by-value fn item is ignored, so the shim has
-                // the same signature as the original function.
-                return llfn;
-            }
-            Some(llfn)
-        }
-        _ => None
-    };
-
-    let bare_fn_ty_maybe_ref = if is_by_ref {
-        tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), bare_fn_ty)
-    } else {
-        bare_fn_ty
-    };
-
-    // Check if we already trans'd this shim.
-    if let Some(&llval) = ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) {
-        return llval;
-    }
-
-    debug!("trans_fn_pointer_shim(bare_fn_ty={:?})",
-           bare_fn_ty);
-
-    // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
-    // which is the fn pointer, and `args`, which is the arguments tuple.
-    let sig = bare_fn_ty.fn_sig();
-    let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
-    assert_eq!(sig.unsafety, hir::Unsafety::Normal);
-    assert_eq!(sig.abi, Abi::Rust);
-    let tuple_input_ty = tcx.intern_tup(sig.inputs(), false);
-    let sig = tcx.mk_fn_sig(
-        [bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(),
-        sig.output(),
-        false,
-        hir::Unsafety::Normal,
-        Abi::RustCall
-    );
-    let fn_ty = FnType::new(ccx, sig, &[]);
-    let tuple_fn_ty = tcx.mk_fn_ptr(ty::Binder(sig));
-    debug!("tuple_fn_ty: {:?}", tuple_fn_ty);
-
-    //
-    let function_name = method_instance.symbol_name(ccx.shared());
-    let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
-    attributes::set_frame_pointer_elimination(ccx, llfn);
-    //
-    let bcx = Builder::new_block(ccx, llfn, "entry-block");
-
-    let mut llargs = get_params(llfn);
-
-    let self_arg = llargs.remove(fn_ty.ret.is_indirect() as usize);
-    let llfnpointer = llfnpointer.unwrap_or_else(|| {
-        // the first argument (`self`) will be ptr to the fn pointer
-        if is_by_ref {
-            bcx.load(self_arg, None)
-        } else {
-            self_arg
-        }
-    });
-
-    let callee = Callee {
-        data: Fn(llfnpointer),
-        ty: bare_fn_ty
-    };
-    let fn_ret = callee.ty.fn_ret();
-    let fn_ty = callee.direct_fn_type(ccx, &[]);
-    let llret = bcx.call(llfnpointer, &llargs, None);
-    fn_ty.apply_attrs_callsite(llret);
-
-    if fn_ret.0.is_never() {
-        bcx.unreachable();
-    } else {
-        if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
-            bcx.ret_void();
-        } else {
-            bcx.ret(llret);
-        }
-    }
-
-    ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);
-
-    llfn
-}
+use rustc::ty::TypeFoldable;
 
 /// Translates a reference to a fn/method item, monomorphizing and
 /// inlining as it goes.
@@ -519,26 +33,22 @@ fn trans_fn_pointer_shim<'a, 'tcx>(
 /// # Parameters
 ///
 /// - `ccx`: the crate context
-/// - `def_id`: def id of the fn or method item being referenced
-/// - `substs`: values for each of the fn/method's parameters
-fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                    def_id: DefId,
-                    substs: &'tcx Substs<'tcx>)
-                    -> (ValueRef, Ty<'tcx>) {
+/// - `instance`: the instance to be instantiated
+pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                        instance: Instance<'tcx>)
+                        -> ValueRef
+{
     let tcx = ccx.tcx();
 
-    debug!("get_fn(def_id={:?}, substs={:?})", def_id, substs);
-
-    assert!(!substs.needs_infer());
-    assert!(!substs.has_escaping_regions());
-    assert!(!substs.has_param_types());
+    debug!("get_fn(instance={:?})", instance);
 
-    let substs = tcx.normalize_associated_type(&substs);
-    let instance = Instance::new(def_id, substs);
-    let fn_ty = common::def_ty(ccx.shared(), def_id, substs);
+    assert!(!instance.substs.needs_infer());
+    assert!(!instance.substs.has_escaping_regions());
+    assert!(!instance.substs.has_param_types());
 
+    let fn_ty = common::instance_ty(ccx.shared(), &instance);
     if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
-        return (llfn, fn_ty);
+        return llfn;
     }
 
     let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
@@ -586,7 +96,10 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         assert_eq!(common::val_ty(llfn), llptrty);
         debug!("get_fn: not casting pointer!");
 
-        let attrs = ccx.tcx().get_attrs(def_id);
+        if common::is_inline_instance(tcx, &instance) {
+            attributes::inline(llfn, attributes::InlineAttr::Hint);
+        }
+        let attrs = instance.def.attrs(ccx.tcx());
         attributes::from_fn_attrs(ccx, &attrs, llfn);
 
         let is_local_def = ccx.shared().translation_items().borrow()
@@ -598,7 +111,9 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
             }
         }
-        if ccx.use_dll_storage_attrs() && ccx.sess().cstore.is_dllimport_foreign_item(def_id) {
+        if ccx.use_dll_storage_attrs() &&
+            ccx.sess().cstore.is_dllimport_foreign_item(instance.def_id())
+        {
             unsafe {
                 llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
             }
@@ -608,5 +123,13 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     ccx.instances().borrow_mut().insert(instance, llfn);
 
-    (llfn, fn_ty)
+    llfn
+}
+
+pub fn resolve_and_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                    def_id: DefId,
+                                    substs: &'tcx Substs<'tcx>)
+                                    -> ValueRef
+{
+    get_fn(ccx, monomorphize::resolve(ccx.shared(), def_id, substs))
 }
diff --git a/src/librustc_trans/cleanup.rs b/src/librustc_trans/cleanup.rs
deleted file mode 100644 (file)
index 5d89a67..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! ## The Cleanup module
-//!
-//! The cleanup module tracks what values need to be cleaned up as scopes
-//! are exited, either via panic or just normal control flow.
-//!
-//! Cleanup items can be scheduled into any of the scopes on the stack.
-//! Typically, when a scope is finished, we generate the cleanup code. This
-//! corresponds to a normal exit from a block (for example, an expression
-//! completing evaluation successfully without panic).
-
-use llvm::BasicBlockRef;
-use base;
-use mir::lvalue::LvalueRef;
-use rustc::mir::tcx::LvalueTy;
-use builder::Builder;
-use common::Funclet;
-use glue;
-use type_::Type;
-
-pub struct CleanupScope<'tcx> {
-    // Cleanup to run upon scope exit.
-    cleanup: Option<DropValue<'tcx>>,
-
-    // Computed on creation if compiling with landing pads (!sess.no_landing_pads)
-    pub landing_pad: Option<BasicBlockRef>,
-}
-
-#[derive(Copy, Clone)]
-pub struct DropValue<'tcx> {
-    val: LvalueRef<'tcx>,
-    skip_dtor: bool,
-}
-
-impl<'tcx> DropValue<'tcx> {
-    fn trans<'a>(&self, funclet: Option<&'a Funclet>, bcx: &Builder<'a, 'tcx>) {
-        glue::call_drop_glue(bcx, self.val, self.skip_dtor, funclet)
-    }
-
-    /// Creates a landing pad for the top scope. The landing pad will perform all cleanups necessary
-    /// for an unwind and then `resume` to continue error propagation:
-    ///
-    ///     landing_pad -> ... cleanups ... -> [resume]
-    ///
-    /// This should only be called once per function, as it creates an alloca for the landingpad.
-    fn get_landing_pad<'a>(&self, bcx: &Builder<'a, 'tcx>) -> BasicBlockRef {
-        debug!("get_landing_pad");
-        let bcx = bcx.build_sibling_block("cleanup_unwind");
-        let llpersonality = bcx.ccx.eh_personality();
-        bcx.set_personality_fn(llpersonality);
-
-        if base::wants_msvc_seh(bcx.sess()) {
-            let pad = bcx.cleanup_pad(None, &[]);
-            let funclet = Some(Funclet::new(pad));
-            self.trans(funclet.as_ref(), &bcx);
-
-            bcx.cleanup_ret(pad, None);
-        } else {
-            // The landing pad return type (the type being propagated). Not sure
-            // what this represents but it's determined by the personality
-            // function and this is what the EH proposal example uses.
-            let llretty = Type::struct_(bcx.ccx, &[Type::i8p(bcx.ccx), Type::i32(bcx.ccx)], false);
-
-            // The only landing pad clause will be 'cleanup'
-            let llretval = bcx.landing_pad(llretty, llpersonality, 1, bcx.llfn());
-
-            // The landing pad block is a cleanup
-            bcx.set_cleanup(llretval);
-
-            // Insert cleanup instructions into the cleanup block
-            self.trans(None, &bcx);
-
-            if !bcx.sess().target.target.options.custom_unwind_resume {
-                bcx.resume(llretval);
-            } else {
-                let exc_ptr = bcx.extract_value(llretval, 0);
-                bcx.call(bcx.ccx.eh_unwind_resume(), &[exc_ptr], None);
-                bcx.unreachable();
-            }
-        }
-
-        bcx.llbb()
-    }
-}
-
-impl<'a, 'tcx> CleanupScope<'tcx> {
-    /// Schedules a (deep) drop of `val`, which is a pointer to an instance of `ty`
-    pub fn schedule_drop_mem(
-        bcx: &Builder<'a, 'tcx>, val: LvalueRef<'tcx>
-    ) -> CleanupScope<'tcx> {
-        if let LvalueTy::Downcast { .. } = val.ty {
-            bug!("Cannot drop downcast ty yet");
-        }
-        if !bcx.ccx.shared().type_needs_drop(val.ty.to_ty(bcx.tcx())) {
-            return CleanupScope::noop();
-        }
-        let drop = DropValue {
-            val: val,
-            skip_dtor: false,
-        };
-
-        CleanupScope::new(bcx, drop)
-    }
-
-    /// Issue #23611: Schedules a (deep) drop of the contents of
-    /// `val`, which is a pointer to an instance of struct/enum type
-    /// `ty`. The scheduled code handles extracting the discriminant
-    /// and dropping the contents associated with that variant
-    /// *without* executing any associated drop implementation.
-    pub fn schedule_drop_adt_contents(
-        bcx: &Builder<'a, 'tcx>, val: LvalueRef<'tcx>
-    ) -> CleanupScope<'tcx> {
-        if let LvalueTy::Downcast { .. } = val.ty {
-            bug!("Cannot drop downcast ty yet");
-        }
-        // `if` below could be "!contents_needs_drop"; skipping drop
-        // is just an optimization, so sound to be conservative.
-        if !bcx.ccx.shared().type_needs_drop(val.ty.to_ty(bcx.tcx())) {
-            return CleanupScope::noop();
-        }
-
-        let drop = DropValue {
-            val: val,
-            skip_dtor: true,
-        };
-
-        CleanupScope::new(bcx, drop)
-    }
-
-    fn new(bcx: &Builder<'a, 'tcx>, drop_val: DropValue<'tcx>) -> CleanupScope<'tcx> {
-        CleanupScope {
-            cleanup: Some(drop_val),
-            landing_pad: if !bcx.sess().no_landing_pads() {
-                Some(drop_val.get_landing_pad(bcx))
-            } else {
-                None
-            },
-        }
-    }
-
-    pub fn noop() -> CleanupScope<'tcx> {
-        CleanupScope {
-            cleanup: None,
-            landing_pad: None,
-        }
-    }
-
-    pub fn trans(self, bcx: &'a Builder<'a, 'tcx>) {
-        if let Some(cleanup) = self.cleanup {
-            cleanup.trans(None, &bcx);
-        }
-    }
-}
index 8d1db38999c6b1d5fc2985dd78536160697d4d00..500802a4135d009894d5a6beec787122e910c211 100644 (file)
 
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
-use rustc::middle::lang_items::{BoxFreeFnLangItem, ExchangeMallocFnLangItem};
+use rustc::middle::lang_items::{ExchangeMallocFnLangItem};
 use rustc::traits;
-use rustc::ty::subst::{Kind, Substs, Subst};
+use rustc::ty::subst::{Substs, Subst};
 use rustc::ty::{self, TypeFoldable, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::mir::{self, Location};
-use rustc::mir::visit as mir_visit;
 use rustc::mir::visit::Visitor as MirVisitor;
 
-use syntax::abi::Abi;
-use syntax_pos::DUMMY_SP;
-use base::custom_coerce_unsize_info;
-use callee::needs_fn_once_adapter_shim;
 use context::SharedCrateContext;
-use common::{def_ty, fulfill_obligation};
-use glue::{self, DropGlueKind};
+use common::{def_ty, instance_ty};
 use monomorphize::{self, Instance};
 use util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
 
 use trans_item::{TransItem, DefPathBasedNames, InstantiationMode};
 
-use std::iter;
-
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum TransItemCollectionMode {
     Eager,
@@ -331,27 +323,23 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
     let recursion_depth_reset;
 
     match starting_point {
-        TransItem::DropGlue(t) => {
-            find_drop_glue_neighbors(scx, t, &mut neighbors);
-            recursion_depth_reset = None;
-        }
         TransItem::Static(node_id) => {
             let def_id = scx.tcx().hir.local_def_id(node_id);
+            let instance = Instance::mono(scx.tcx(), def_id);
 
             // Sanity check whether this ended up being collected accidentally
-            debug_assert!(should_trans_locally(scx.tcx(), def_id));
+            debug_assert!(should_trans_locally(scx.tcx(), &instance));
 
-            let ty = def_ty(scx, def_id, Substs::empty());
-            let ty = glue::get_drop_glue_type(scx, ty);
-            neighbors.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
+            let ty = instance_ty(scx, &instance);
+            visit_drop_use(scx, ty, true, &mut neighbors);
 
             recursion_depth_reset = None;
 
-            collect_neighbours(scx, Instance::mono(scx, def_id), &mut neighbors);
+            collect_neighbours(scx, instance, &mut neighbors);
         }
         TransItem::Fn(instance) => {
             // Sanity check whether this ended up being collected accidentally
-            debug_assert!(should_trans_locally(scx.tcx(), instance.def));
+            debug_assert!(should_trans_locally(scx.tcx(), &instance));
 
             // Keep track of the monomorphization recursion depth
             recursion_depth_reset = Some(check_recursion_limit(scx.tcx(),
@@ -395,27 +383,34 @@ fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    instance: Instance<'tcx>,
                                    recursion_depths: &mut DefIdMap<usize>)
                                    -> (DefId, usize) {
-    let recursion_depth = recursion_depths.get(&instance.def)
-                                          .map(|x| *x)
-                                          .unwrap_or(0);
+    let def_id = instance.def_id();
+    let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
     debug!(" => recursion depth={}", recursion_depth);
 
+    let recursion_depth = if Some(def_id) == tcx.lang_items.drop_in_place_fn() {
+        // HACK: drop_in_place creates tight monomorphization loops. Give
+        // it more margin.
+        recursion_depth / 4
+    } else {
+        recursion_depth
+    };
+
     // Code that needs to instantiate the same function recursively
     // more than the recursion limit is assumed to be causing an
     // infinite expansion.
     if recursion_depth > tcx.sess.recursion_limit.get() {
         let error = format!("reached the recursion limit while instantiating `{}`",
                             instance);
-        if let Some(node_id) = tcx.hir.as_local_node_id(instance.def) {
+        if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
             tcx.sess.span_fatal(tcx.hir.span(node_id), &error);
         } else {
             tcx.sess.fatal(&error);
         }
     }
 
-    recursion_depths.insert(instance.def, recursion_depth + 1);
+    recursion_depths.insert(def_id, recursion_depth + 1);
 
-    (instance.def, recursion_depth)
+    (def_id, recursion_depth)
 }
 
 fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -438,7 +433,7 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let instance_name = instance.to_string();
         let msg = format!("reached the type-length limit while instantiating `{:.64}...`",
                           instance_name);
-        let mut diag = if let Some(node_id) = tcx.hir.as_local_node_id(instance.def) {
+        let mut diag = if let Some(node_id) = tcx.hir.as_local_node_id(instance.def_id()) {
             tcx.sess.struct_span_fatal(tcx.hir.span(node_id), &msg)
         } else {
             tcx.sess.struct_fatal(&msg)
@@ -489,37 +484,34 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
                                                           self.output);
                 }
             }
+            mir::Rvalue::Cast(mir::CastKind::ReifyFnPointer, ref operand, _) => {
+                let fn_ty = operand.ty(self.mir, self.scx.tcx());
+                let fn_ty = monomorphize::apply_param_substs(
+                    self.scx,
+                    self.param_substs,
+                    &fn_ty);
+                visit_fn_use(self.scx, fn_ty, false, &mut self.output);
+            }
             mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer, ref operand, _) => {
                 let source_ty = operand.ty(self.mir, self.scx.tcx());
                 match source_ty.sty {
                     ty::TyClosure(def_id, substs) => {
-                        let closure_trans_item =
-                            create_fn_trans_item(self.scx,
-                                                 def_id,
-                                                 substs.substs,
-                                                 self.param_substs);
-                        self.output.push(closure_trans_item);
+                        let instance = monomorphize::resolve_closure(
+                            self.scx, def_id, substs, ty::ClosureKind::FnOnce);
+                        self.output.push(create_fn_trans_item(instance));
                     }
                     _ => bug!(),
                 }
             }
             mir::Rvalue::Box(..) => {
-                let exchange_malloc_fn_def_id =
-                    self.scx
-                        .tcx()
-                        .lang_items
-                        .require(ExchangeMallocFnLangItem)
-                        .unwrap_or_else(|e| self.scx.sess().fatal(&e));
-
-                if should_trans_locally(self.scx.tcx(), exchange_malloc_fn_def_id) {
-                    let empty_substs = self.scx.empty_substs_for_def_id(exchange_malloc_fn_def_id);
-                    let exchange_malloc_fn_trans_item =
-                        create_fn_trans_item(self.scx,
-                                             exchange_malloc_fn_def_id,
-                                             empty_substs,
-                                             self.param_substs);
-
-                    self.output.push(exchange_malloc_fn_trans_item);
+                let tcx = self.scx.tcx();
+                let exchange_malloc_fn_def_id = tcx
+                    .lang_items
+                    .require(ExchangeMallocFnLangItem)
+                    .unwrap_or_else(|e| self.scx.sess().fatal(&e));
+                let instance = Instance::mono(tcx, exchange_malloc_fn_def_id);
+                if should_trans_locally(tcx, &instance) {
+                    self.output.push(create_fn_trans_item(instance));
                 }
             }
             _ => { /* not interesting */ }
@@ -528,461 +520,156 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
         self.super_rvalue(rvalue, location);
     }
 
-    fn visit_lvalue(&mut self,
-                    lvalue: &mir::Lvalue<'tcx>,
-                    context: mir_visit::LvalueContext<'tcx>,
-                    location: Location) {
-        debug!("visiting lvalue {:?}", *lvalue);
-
-        if let mir_visit::LvalueContext::Drop = context {
-            let ty = lvalue.ty(self.mir, self.scx.tcx())
-                           .to_ty(self.scx.tcx());
-
-            let ty = monomorphize::apply_param_substs(self.scx,
-                                                      self.param_substs,
-                                                      &ty);
-            assert!(ty.is_normalized_for_trans());
-            let ty = glue::get_drop_glue_type(self.scx, ty);
-            self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
-        }
-
-        self.super_lvalue(lvalue, context, location);
-    }
-
-    fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
-        debug!("visiting operand {:?}", *operand);
-
-        let callee = match *operand {
-            mir::Operand::Constant(ref constant) => {
-                if let ty::TyFnDef(def_id, substs, _) = constant.ty.sty {
-                    // This is something that can act as a callee, proceed
-                    Some((def_id, substs))
-                } else {
-                    // This is not a callee, but we still have to look for
-                    // references to `const` items
-                    if let mir::Literal::Item { def_id, substs } = constant.literal {
-                        let substs = monomorphize::apply_param_substs(self.scx,
-                                                                      self.param_substs,
-                                                                      &substs);
-
-                        let instance = Instance::new(def_id, substs).resolve_const(self.scx);
-                        collect_neighbours(self.scx, instance, self.output);
-                    }
-
-                    None
-                }
-            }
-            _ => None
-        };
+    fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) {
+        debug!("visiting constant {:?} @ {:?}", *constant, location);
 
-        if let Some((callee_def_id, callee_substs)) = callee {
-            debug!(" => operand is callable");
-
-            // `callee_def_id` might refer to a trait method instead of a
-            // concrete implementation, so we have to find the actual
-            // implementation. For example, the call might look like
-            //
-            // std::cmp::partial_cmp(0i32, 1i32)
-            //
-            // Calling do_static_dispatch() here will map the def_id of
-            // `std::cmp::partial_cmp` to the def_id of `i32::partial_cmp<i32>`
-            let dispatched = do_static_dispatch(self.scx,
-                                                callee_def_id,
-                                                callee_substs,
-                                                self.param_substs);
-
-            if let StaticDispatchResult::Dispatched {
-                    def_id: callee_def_id,
-                    substs: callee_substs,
-                    fn_once_adjustment,
-                } = dispatched {
-                // if we have a concrete impl (which we might not have
-                // in the case of something compiler generated like an
-                // object shim or a closure that is handled differently),
-                // we check if the callee is something that will actually
-                // result in a translation item ...
-                if can_result_in_trans_item(self.scx.tcx(), callee_def_id) {
-                    // ... and create one if it does.
-                    let trans_item = create_fn_trans_item(self.scx,
-                                                          callee_def_id,
-                                                          callee_substs,
-                                                          self.param_substs);
-                    self.output.push(trans_item);
-
-                    // This call will instantiate an FnOnce adapter, which drops
-                    // the closure environment. Therefore we need to make sure
-                    // that we collect the drop-glue for the environment type.
-                    if let Some(env_ty) = fn_once_adjustment {
-                        let env_ty = glue::get_drop_glue_type(self.scx, env_ty);
-                        if self.scx.type_needs_drop(env_ty) {
-                            let dg = DropGlueKind::Ty(env_ty);
-                            self.output.push(TransItem::DropGlue(dg));
-                        }
-                    }
-                }
-            }
+        if let ty::TyFnDef(..) = constant.ty.sty {
+            // function definitions are zero-sized, and only generate
+            // IR when they are called/reified.
+            self.super_constant(constant, location);
+            return
         }
 
-        self.super_operand(operand, location);
-
-        fn can_result_in_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                              def_id: DefId)
-                                              -> bool {
-            match tcx.item_type(def_id).sty {
-                ty::TyFnDef(def_id, _, _) => {
-                    // Some constructors also have type TyFnDef but they are
-                    // always instantiated inline and don't result in a
-                    // translation item. Same for FFI functions.
-                    if let Some(hir_map::NodeForeignItem(_)) = tcx.hir.get_if_local(def_id) {
-                        return false;
-                    }
-                }
-                ty::TyClosure(..) => {}
-                _ => return false
-            }
-
-            should_trans_locally(tcx, def_id)
+        if let mir::Literal::Item { def_id, substs } = constant.literal {
+            let substs = monomorphize::apply_param_substs(self.scx,
+                                                          self.param_substs,
+                                                          &substs);
+            let instance = monomorphize::resolve(self.scx, def_id, substs);
+            collect_neighbours(self.scx, instance, self.output);
         }
+
+        self.super_constant(constant, location);
     }
 
-    // This takes care of the "drop_in_place" intrinsic for which we otherwise
-    // we would not register drop-glues.
     fn visit_terminator_kind(&mut self,
                              block: mir::BasicBlock,
                              kind: &mir::TerminatorKind<'tcx>,
                              location: Location) {
         let tcx = self.scx.tcx();
         match *kind {
-            mir::TerminatorKind::Call {
-                func: mir::Operand::Constant(ref constant),
-                ref args,
-                ..
-            } => {
-                match constant.ty.sty {
-                    ty::TyFnDef(def_id, _, bare_fn_ty)
-                        if is_drop_in_place_intrinsic(tcx, def_id, bare_fn_ty) => {
-                        let operand_ty = args[0].ty(self.mir, tcx);
-                        if let ty::TyRawPtr(mt) = operand_ty.sty {
-                            let operand_ty = monomorphize::apply_param_substs(self.scx,
-                                                                              self.param_substs,
-                                                                              &mt.ty);
-                            let ty = glue::get_drop_glue_type(self.scx, operand_ty);
-                            self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
-                        } else {
-                            bug!("Has the drop_in_place() intrinsic's signature changed?")
-                        }
-                    }
-                    _ => { /* Nothing to do. */ }
-                }
+            mir::TerminatorKind::Call { ref func, .. } => {
+                let callee_ty = func.ty(self.mir, tcx);
+                let callee_ty = monomorphize::apply_param_substs(
+                    self.scx, self.param_substs, &callee_ty);
+                visit_fn_use(self.scx, callee_ty, true, &mut self.output);
+            }
+            mir::TerminatorKind::Drop { ref location, .. } |
+            mir::TerminatorKind::DropAndReplace { ref location, .. } => {
+                let ty = location.ty(self.mir, self.scx.tcx())
+                    .to_ty(self.scx.tcx());
+                let ty = monomorphize::apply_param_substs(self.scx,
+                                                          self.param_substs,
+                                                          &ty);
+                visit_drop_use(self.scx, ty, true, self.output);
             }
-            _ => { /* Nothing to do. */ }
+            mir::TerminatorKind::Goto { .. } |
+            mir::TerminatorKind::SwitchInt { .. } |
+            mir::TerminatorKind::Resume |
+            mir::TerminatorKind::Return |
+            mir::TerminatorKind::Unreachable |
+            mir::TerminatorKind::Assert { .. } => {}
         }
 
         self.super_terminator_kind(block, kind, location);
-
-        fn is_drop_in_place_intrinsic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                                def_id: DefId,
-                                                bare_fn_ty: ty::PolyFnSig<'tcx>)
-                                                -> bool {
-            (bare_fn_ty.abi() == Abi::RustIntrinsic ||
-             bare_fn_ty.abi() == Abi::PlatformIntrinsic) &&
-            tcx.item_name(def_id) == "drop_in_place"
-        }
     }
 }
 
-// Returns true if we should translate an instance in the local crate.
-// Returns false if we can just link to the upstream crate and therefore don't
-// need a translation item.
-fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  def_id: DefId)
-                                  -> bool {
-    if let ty::TyFnDef(_, _, sig) = tcx.item_type(def_id).sty {
-        if let Some(adt_def) = sig.output().skip_binder().ty_adt_def() {
-            if adt_def.variants.iter().any(|v| def_id == v.did) {
-                // HACK: ADT constructors are translated in-place and
-                // do not have a trans-item.
-                return false;
-            }
-        }
-    }
-
-    if def_id.is_local() {
-        true
-    } else {
-        if tcx.sess.cstore.is_exported_symbol(def_id) ||
-           tcx.sess.cstore.is_foreign_item(def_id) {
-            // We can link to the item in question, no instance needed in this
-            // crate
-            false
-        } else {
-            if !tcx.sess.cstore.is_item_mir_available(def_id) {
-                bug!("Cannot create local trans-item for {:?}", def_id)
-            }
-            true
-        }
-    }
+fn visit_drop_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
+                            ty: ty::Ty<'tcx>,
+                            is_direct_call: bool,
+                            output: &mut Vec<TransItem<'tcx>>)
+{
+    let instance = monomorphize::resolve_drop_in_place(scx, ty);
+    visit_instance_use(scx, instance, is_direct_call, output);
 }
 
-fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                      dg: DropGlueKind<'tcx>,
-                                      output: &mut Vec<TransItem<'tcx>>) {
-    let ty = match dg {
-        DropGlueKind::Ty(ty) => ty,
-        DropGlueKind::TyContents(_) => {
-            // We already collected the neighbors of this item via the
-            // DropGlueKind::Ty variant.
-            return
-        }
-    };
-
-    debug!("find_drop_glue_neighbors: {}", type_to_string(scx.tcx(), ty));
-
-    // Make sure the BoxFreeFn lang-item gets translated if there is a boxed value.
-    if ty.is_box() {
-        let def_id = scx.tcx().require_lang_item(BoxFreeFnLangItem);
-        if should_trans_locally(scx.tcx(), def_id) {
-            let box_free_fn_trans_item =
-                create_fn_trans_item(scx,
-                                     def_id,
-                                     scx.tcx().mk_substs(iter::once(Kind::from(ty.boxed_ty()))),
-                                     scx.tcx().intern_substs(&[]));
-            output.push(box_free_fn_trans_item);
-        }
+fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
+                          ty: ty::Ty<'tcx>,
+                          is_direct_call: bool,
+                          output: &mut Vec<TransItem<'tcx>>)
+{
+    if let ty::TyFnDef(def_id, substs, _) = ty.sty {
+        let instance = monomorphize::resolve(scx, def_id, substs);
+        visit_instance_use(scx, instance, is_direct_call, output);
     }
+}
 
-    // If the type implements Drop, also add a translation item for the
-    // monomorphized Drop::drop() implementation.
-    let destructor = match ty.sty {
-        ty::TyAdt(def, _) => def.destructor(scx.tcx()),
-        _ => None
-    };
-
-    if let (Some(destructor), false) = (destructor, ty.is_box()) {
-        use rustc::ty::ToPolyTraitRef;
-
-        let drop_trait_def_id = scx.tcx()
-                                   .lang_items
-                                   .drop_trait()
-                                   .unwrap();
-
-        let self_type_substs = scx.tcx().mk_substs_trait(ty, &[]);
-
-        let trait_ref = ty::TraitRef {
-            def_id: drop_trait_def_id,
-            substs: self_type_substs,
-        }.to_poly_trait_ref();
-
-        let substs = match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
-            traits::VtableImpl(data) => data.substs,
-            _ => bug!()
-        };
-
-        if should_trans_locally(scx.tcx(), destructor.did) {
-            let trans_item = create_fn_trans_item(scx,
-                                                  destructor.did,
-                                                  substs,
-                                                  scx.tcx().intern_substs(&[]));
-            output.push(trans_item);
-        }
-
-        // This type has a Drop implementation, we'll need the contents-only
-        // version of the glue too.
-        output.push(TransItem::DropGlue(DropGlueKind::TyContents(ty)));
+fn visit_instance_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
+                                instance: ty::Instance<'tcx>,
+                                is_direct_call: bool,
+                                output: &mut Vec<TransItem<'tcx>>)
+{
+    debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
+    if !should_trans_locally(scx.tcx(), &instance) {
+        return
     }
 
-    // Finally add the types of nested values
-    match ty.sty {
-        ty::TyBool      |
-        ty::TyChar      |
-        ty::TyInt(_)    |
-        ty::TyUint(_)   |
-        ty::TyStr       |
-        ty::TyFloat(_)  |
-        ty::TyRawPtr(_) |
-        ty::TyRef(..)   |
-        ty::TyFnDef(..) |
-        ty::TyFnPtr(_)  |
-        ty::TyNever     |
-        ty::TyDynamic(..)  => {
-            /* nothing to do */
-        }
-        ty::TyAdt(def, _) if def.is_box() => {
-            let inner_type = glue::get_drop_glue_type(scx, ty.boxed_ty());
-            if scx.type_needs_drop(inner_type) {
-                output.push(TransItem::DropGlue(DropGlueKind::Ty(inner_type)));
-            }
-        }
-        ty::TyAdt(def, substs) => {
-            for field in def.all_fields() {
-                let field_type = def_ty(scx, field.did, substs);
-                let field_type = glue::get_drop_glue_type(scx, field_type);
-
-                if scx.type_needs_drop(field_type) {
-                    output.push(TransItem::DropGlue(DropGlueKind::Ty(field_type)));
-                }
+    match instance.def {
+        ty::InstanceDef::Intrinsic(def_id) => {
+            if !is_direct_call {
+                bug!("intrinsic {:?} being reified", def_id);
             }
         }
-        ty::TyClosure(def_id, substs) => {
-            for upvar_ty in substs.upvar_tys(def_id, scx.tcx()) {
-                let upvar_ty = glue::get_drop_glue_type(scx, upvar_ty);
-                if scx.type_needs_drop(upvar_ty) {
-                    output.push(TransItem::DropGlue(DropGlueKind::Ty(upvar_ty)));
-                }
-            }
-        }
-        ty::TySlice(inner_type)    |
-        ty::TyArray(inner_type, _) => {
-            let inner_type = glue::get_drop_glue_type(scx, inner_type);
-            if scx.type_needs_drop(inner_type) {
-                output.push(TransItem::DropGlue(DropGlueKind::Ty(inner_type)));
+        ty::InstanceDef::Virtual(..) |
+        ty::InstanceDef::DropGlue(_, None) => {
+            // don't need to emit shim if we are calling directly.
+            if !is_direct_call {
+                output.push(create_fn_trans_item(instance));
             }
         }
-        ty::TyTuple(args, _) => {
-            for arg in args {
-                let arg = glue::get_drop_glue_type(scx, arg);
-                if scx.type_needs_drop(arg) {
-                    output.push(TransItem::DropGlue(DropGlueKind::Ty(arg)));
+        ty::InstanceDef::DropGlue(_, Some(ty)) => {
+            match ty.sty {
+                ty::TyArray(ety, _) |
+                ty::TySlice(ety)
+                    if is_direct_call =>
+                {
+                    // drop of arrays/slices is translated in-line.
+                    visit_drop_use(scx, ety, false, output);
                 }
-            }
-        }
-        ty::TyProjection(_) |
-        ty::TyParam(_)      |
-        ty::TyInfer(_)      |
-        ty::TyAnon(..)      |
-        ty::TyError         => {
-            bug!("encountered unexpected type");
+                _ => {}
+            };
+            output.push(create_fn_trans_item(instance));
         }
-    }
-}
-
-fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                fn_def_id: DefId,
-                                fn_substs: &'tcx Substs<'tcx>,
-                                param_substs: &'tcx Substs<'tcx>)
-                                -> StaticDispatchResult<'tcx> {
-    debug!("do_static_dispatch(fn_def_id={}, fn_substs={:?}, param_substs={:?})",
-           def_id_to_string(scx.tcx(), fn_def_id),
-           fn_substs,
-           param_substs);
-
-    if let Some(trait_def_id) = scx.tcx().trait_of_item(fn_def_id) {
-        debug!(" => trait method, attempting to find impl");
-        do_static_trait_method_dispatch(scx,
-                                        &scx.tcx().associated_item(fn_def_id),
-                                        trait_def_id,
-                                        fn_substs,
-                                        param_substs)
-    } else {
-        debug!(" => regular function");
-        // The function is not part of an impl or trait, no dispatching
-        // to be done
-        StaticDispatchResult::Dispatched {
-            def_id: fn_def_id,
-            substs: fn_substs,
-            fn_once_adjustment: None,
+        ty::InstanceDef::ClosureOnceShim { .. } |
+        ty::InstanceDef::Item(..) |
+        ty::InstanceDef::FnPtrShim(..) => {
+            output.push(create_fn_trans_item(instance));
         }
     }
 }
 
-enum StaticDispatchResult<'tcx> {
-    // The call could be resolved statically as going to the method with
-    // `def_id` and `substs`.
-    Dispatched {
-        def_id: DefId,
-        substs: &'tcx Substs<'tcx>,
-
-        // If this is a call to a closure that needs an FnOnce adjustment,
-        // this contains the new self type of the call (= type of the closure
-        // environment)
-        fn_once_adjustment: Option<ty::Ty<'tcx>>,
-    },
-    // This goes to somewhere that we don't know at compile-time
-    Unknown
-}
-
-// Given a trait-method and substitution information, find out the actual
-// implementation of the trait method.
-fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                             trait_method: &ty::AssociatedItem,
-                                             trait_id: DefId,
-                                             callee_substs: &'tcx Substs<'tcx>,
-                                             param_substs: &'tcx Substs<'tcx>)
-                                             -> StaticDispatchResult<'tcx> {
-    let tcx = scx.tcx();
-    debug!("do_static_trait_method_dispatch(trait_method={}, \
-                                            trait_id={}, \
-                                            callee_substs={:?}, \
-                                            param_substs={:?}",
-           def_id_to_string(scx.tcx(), trait_method.def_id),
-           def_id_to_string(scx.tcx(), trait_id),
-           callee_substs,
-           param_substs);
-
-    let rcvr_substs = monomorphize::apply_param_substs(scx,
-                                                       param_substs,
-                                                       &callee_substs);
-    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
-    let vtbl = fulfill_obligation(scx, DUMMY_SP, ty::Binder(trait_ref));
-
-    // Now that we know which impl is being used, we can dispatch to
-    // the actual function:
-    match vtbl {
-        traits::VtableImpl(impl_data) => {
-            let (def_id, substs) = traits::find_method(tcx,
-                                                       trait_method.name,
-                                                       rcvr_substs,
-                                                       &impl_data);
-            StaticDispatchResult::Dispatched {
-                def_id: def_id,
-                substs: substs,
-                fn_once_adjustment: None,
-            }
-        }
-        traits::VtableClosure(closure_data) => {
-            let closure_def_id = closure_data.closure_def_id;
-            let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
-            let actual_closure_kind = tcx.closure_kind(closure_def_id);
-
-            let needs_fn_once_adapter_shim =
-                match needs_fn_once_adapter_shim(actual_closure_kind,
-                                                 trait_closure_kind) {
-                Ok(true) => true,
-                _ => false,
-            };
-
-            let fn_once_adjustment = if needs_fn_once_adapter_shim {
-                Some(tcx.mk_closure_from_closure_substs(closure_def_id,
-                                                        closure_data.substs))
-            } else {
-                None
-            };
-
-            StaticDispatchResult::Dispatched {
-                def_id: closure_def_id,
-                substs: closure_data.substs.substs,
-                fn_once_adjustment: fn_once_adjustment,
-            }
-        }
-        traits::VtableFnPointer(ref data) => {
-            // If we know the destination of this fn-pointer, we'll have to make
-            // sure that this destination actually gets instantiated.
-            if let ty::TyFnDef(def_id, substs, _) = data.fn_ty.sty {
-                // The destination of the pointer might be something that needs
-                // further dispatching, such as a trait method, so we do that.
-                do_static_dispatch(scx, def_id, substs, param_substs)
+// Returns true if we should translate an instance in the local crate.
+// Returns false if we can just link to the upstream crate and therefore don't
+// need a translation item.
+fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &Instance<'tcx>)
+                                  -> bool {
+    let def_id = match instance.def {
+        ty::InstanceDef::Item(def_id) => def_id,
+        ty::InstanceDef::ClosureOnceShim { .. } |
+        ty::InstanceDef::Virtual(..) |
+        ty::InstanceDef::FnPtrShim(..) |
+        ty::InstanceDef::DropGlue(..) |
+        ty::InstanceDef::Intrinsic(_) => return true
+    };
+    match tcx.hir.get_if_local(def_id) {
+        Some(hir_map::NodeForeignItem(..)) => {
+            false // foreign items are linked against, not translated.
+        }
+        Some(_) => true,
+        None => {
+            if tcx.sess.cstore.is_exported_symbol(def_id) ||
+                tcx.sess.cstore.is_foreign_item(def_id)
+            {
+                // We can link to the item in question, no instance needed
+                // in this crate
+                false
             } else {
-                StaticDispatchResult::Unknown
+                if !tcx.sess.cstore.is_item_mir_available(def_id) {
+                    bug!("Cannot create local trans-item for {:?}", def_id)
+                }
+                true
             }
         }
-        // Trait object shims are always instantiated in-place, and as they are
-        // just an ABI-adjusting indirect call they do not have any dependencies.
-        traits::VtableObject(..) => {
-            StaticDispatchResult::Unknown
-        }
-        _ => {
-            bug!("static call to invalid vtable: {:?}", vtbl)
-        }
     }
 }
 
@@ -1051,7 +738,8 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
          &ty::TyAdt(target_adt_def, target_substs)) => {
             assert_eq!(source_adt_def, target_adt_def);
 
-            let kind = custom_coerce_unsize_info(scx, source_ty, target_ty);
+            let kind =
+                monomorphize::custom_coerce_unsize_info(scx, source_ty, target_ty);
 
             let coerce_index = match kind {
                 CustomCoerceUnsized::Struct(i) => i
@@ -1075,28 +763,9 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
     }
 }
 
-fn create_fn_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                  def_id: DefId,
-                                  fn_substs: &'tcx Substs<'tcx>,
-                                  param_substs: &'tcx Substs<'tcx>)
-                                  -> TransItem<'tcx> {
-    let tcx = scx.tcx();
-
-    debug!("create_fn_trans_item(def_id={}, fn_substs={:?}, param_substs={:?})",
-            def_id_to_string(tcx, def_id),
-            fn_substs,
-            param_substs);
-
-    // We only get here, if fn_def_id either designates a local item or
-    // an inlineable external item. Non-inlineable external items are
-    // ignored because we don't want to generate any code for them.
-    let concrete_substs = monomorphize::apply_param_substs(scx,
-                                                           param_substs,
-                                                           &fn_substs);
-    assert!(concrete_substs.is_normalized_for_trans(),
-            "concrete_substs not normalized for trans: {:?}",
-            concrete_substs);
-    TransItem::Fn(Instance::new(def_id, concrete_substs))
+fn create_fn_trans_item<'a, 'tcx>(instance: Instance<'tcx>) -> TransItem<'tcx> {
+    debug!("create_fn_trans_item(instance={})", instance);
+    TransItem::Fn(instance)
 }
 
 /// Creates a `TransItem` for each method that is referenced by the vtable for
@@ -1111,33 +780,18 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
     if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty {
         if let Some(principal) = trait_ty.principal() {
             let poly_trait_ref = principal.with_self_ty(scx.tcx(), impl_ty);
-            let param_substs = scx.tcx().intern_substs(&[]);
-
             assert!(!poly_trait_ref.has_escaping_regions());
 
             // Walk all methods of the trait, including those of its supertraits
             let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref);
             let methods = methods.filter_map(|method| method)
-                .filter_map(|(def_id, substs)| {
-                    if let StaticDispatchResult::Dispatched {
-                        def_id,
-                        substs,
-                        // We already add the drop-glue for the closure env
-                        // unconditionally below.
-                        fn_once_adjustment: _ ,
-                    } = do_static_dispatch(scx, def_id, substs, param_substs) {
-                        Some((def_id, substs))
-                    } else {
-                        None
-                    }
-                })
-                .filter(|&(def_id, _)| should_trans_locally(scx.tcx(), def_id))
-                .map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs));
+                .map(|(def_id, substs)| monomorphize::resolve(scx, def_id, substs))
+                .filter(|&instance| should_trans_locally(scx.tcx(), &instance))
+                .map(|instance| create_fn_trans_item(instance));
             output.extend(methods);
         }
         // Also add the destructor
-        let dg_type = glue::get_drop_glue_type(scx, impl_ty);
-        output.push(TransItem::DropGlue(DropGlueKind::Ty(dg_type)));
+        visit_drop_use(scx, impl_ty, false, output);
     }
 }
 
@@ -1182,8 +836,7 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                                def_id_to_string(self.scx.tcx(), def_id));
 
                         let ty = def_ty(self.scx, def_id, Substs::empty());
-                        let ty = glue::get_drop_glue_type(self.scx, ty);
-                        self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
+                        visit_drop_use(self.scx, ty, true, self.output);
                     }
                 }
             }
@@ -1204,7 +857,7 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                     debug!("RootCollector: ItemFn({})",
                            def_id_to_string(self.scx.tcx(), def_id));
 
-                    let instance = Instance::mono(self.scx, def_id);
+                    let instance = Instance::mono(self.scx.tcx(), def_id);
                     self.output.push(TransItem::Fn(instance));
                 }
             }
@@ -1242,7 +895,7 @@ fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
                     debug!("RootCollector: MethodImplItem({})",
                            def_id_to_string(self.scx.tcx(), def_id));
 
-                    let instance = Instance::mono(self.scx, def_id);
+                    let instance = Instance::mono(self.scx.tcx(), def_id);
                     self.output.push(TransItem::Fn(instance));
                 }
             }
@@ -1285,33 +938,17 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
                         continue;
                     }
 
-                    // The substitutions we have are on the impl, so we grab
-                    // the method type from the impl to substitute into.
-                    let impl_substs = Substs::for_item(tcx, impl_def_id,
-                                                       |_, _| tcx.mk_region(ty::ReErased),
-                                                       |_, _| tcx.types.err);
-                    let impl_data = traits::VtableImplData {
-                        impl_def_id: impl_def_id,
-                        substs: impl_substs,
-                        nested: vec![]
-                    };
-                    let (def_id, substs) = traits::find_method(tcx,
-                                                               method.name,
-                                                               callee_substs,
-                                                               &impl_data);
-
-                    let predicates = tcx.item_predicates(def_id).predicates
-                                        .subst(tcx, substs);
+                    let instance =
+                        monomorphize::resolve(scx, method.def_id, callee_substs);
+
+                    let predicates = tcx.item_predicates(instance.def_id()).predicates
+                        .subst(tcx, instance.substs);
                     if !traits::normalize_and_test_predicates(tcx, predicates) {
                         continue;
                     }
 
-                    if should_trans_locally(tcx, method.def_id) {
-                        let item = create_fn_trans_item(scx,
-                                                        method.def_id,
-                                                        callee_substs,
-                                                        tcx.erase_regions(&substs));
-                        output.push(item);
+                    if should_trans_locally(tcx, &instance) {
+                        output.push(create_fn_trans_item(instance));
                     }
                 }
             }
@@ -1327,7 +964,7 @@ fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
                                 instance: Instance<'tcx>,
                                 output: &mut Vec<TransItem<'tcx>>)
 {
-    let mir = scx.tcx().item_mir(instance.def);
+    let mir = scx.tcx().instance_mir(instance.def);
 
     let mut visitor = MirNeighborCollector {
         scx: scx,
@@ -1351,12 +988,3 @@ fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     printer.push_def_path(def_id, &mut output);
     output
 }
-
-fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            ty: ty::Ty<'tcx>)
-                            -> String {
-    let mut output = String::new();
-    let printer = DefPathBasedNames::new(tcx, false, false);
-    printer.push_type_name(ty, &mut output);
-    output
-}
index a509587f80fd025e1f9b2c1f9b6aab40b41075a5..a0906bb02f5a32893db8c4fff5f754e6ec3b33c3 100644 (file)
@@ -17,7 +17,6 @@
 use llvm::{True, False, Bool, OperandBundleDef};
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
-use rustc::util::common::MemoizationMap;
 use middle::lang_items::LangItem;
 use base;
 use builder::Builder;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::Layout;
 use rustc::ty::subst::{Subst, Substs};
-use rustc::traits::{self, SelectionContext, Reveal};
 use rustc::hir;
 
 use libc::{c_uint, c_char};
 use std::iter;
 
-use syntax::ast;
+use syntax::attr;
 use syntax::symbol::InternedString;
 use syntax_pos::Span;
 
@@ -426,73 +424,6 @@ pub fn is_null(val: ValueRef) -> bool {
     }
 }
 
-/// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
-/// do not (necessarily) resolve all nested obligations on the impl. Note that type check should
-/// guarantee to us that all nested obligations *could be* resolved if we wanted to.
-pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                    span: Span,
-                                    trait_ref: ty::PolyTraitRef<'tcx>)
-                                    -> traits::Vtable<'tcx, ()>
-{
-    let tcx = scx.tcx();
-
-    // Remove any references to regions; this helps improve caching.
-    let trait_ref = tcx.erase_regions(&trait_ref);
-
-    scx.trait_cache().memoize(trait_ref, || {
-        debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
-               trait_ref, trait_ref.def_id());
-
-        // Do the initial selection for the obligation. This yields the
-        // shallow result we are looking for -- that is, what specific impl.
-        tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
-            let mut selcx = SelectionContext::new(&infcx);
-
-            let obligation_cause = traits::ObligationCause::misc(span,
-                                                             ast::DUMMY_NODE_ID);
-            let obligation = traits::Obligation::new(obligation_cause,
-                                                     trait_ref.to_poly_trait_predicate());
-
-            let selection = match selcx.select(&obligation) {
-                Ok(Some(selection)) => selection,
-                Ok(None) => {
-                    // Ambiguity can happen when monomorphizing during trans
-                    // expands to some humongo type that never occurred
-                    // statically -- this humongo type can then overflow,
-                    // leading to an ambiguous result. So report this as an
-                    // overflow bug, since I believe this is the only case
-                    // where ambiguity can result.
-                    debug!("Encountered ambiguity selecting `{:?}` during trans, \
-                            presuming due to overflow",
-                           trait_ref);
-                    tcx.sess.span_fatal(span,
-                        "reached the recursion limit during monomorphization \
-                         (selection ambiguity)");
-                }
-                Err(e) => {
-                    span_bug!(span, "Encountered error `{:?}` selecting `{:?}` during trans",
-                              e, trait_ref)
-                }
-            };
-
-            debug!("fulfill_obligation: selection={:?}", selection);
-
-            // Currently, we use a fulfillment context to completely resolve
-            // all nested obligations. This is because they can inform the
-            // inference of the impl's type parameters.
-            let mut fulfill_cx = traits::FulfillmentContext::new();
-            let vtable = selection.map(|predicate| {
-                debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
-                fulfill_cx.register_predicate_obligation(&infcx, predicate);
-            });
-            let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable);
-
-            info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
-            vtable
-        })
-    })
-}
-
 pub fn langcall(tcx: TyCtxt,
                 span: Option<Span>,
                 msg: &str,
@@ -601,8 +532,31 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 }
 
-pub fn is_closure(tcx: TyCtxt, def_id: DefId) -> bool {
-    tcx.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
+pub fn requests_inline<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    instance: &ty::Instance<'tcx>
+) -> bool {
+    if is_inline_instance(tcx, instance) {
+        return true
+    }
+    attr::requests_inline(&instance.def.attrs(tcx)[..])
+}
+
+pub fn is_inline_instance<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    instance: &ty::Instance<'tcx>
+) -> bool {
+    let def_id = match instance.def {
+        ty::InstanceDef::Item(def_id) => def_id,
+        ty::InstanceDef::DropGlue(_, Some(_)) => return false,
+        _ => return true
+    };
+    match tcx.def_key(def_id).disambiguated_data.data {
+        DefPathData::StructCtor |
+        DefPathData::EnumVariant(..) |
+        DefPathData::ClosureExpr => true,
+        _ => false
+    }
 }
 
 /// Given a DefId and some Substs, produces the monomorphic item type.
@@ -614,3 +568,12 @@ pub fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
     let ty = shared.tcx().item_type(def_id);
     monomorphize::apply_param_substs(shared, substs, &ty)
 }
+
+/// Return the substituted type of an instance.
+pub fn instance_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
+                             instance: &ty::Instance<'tcx>)
+                             -> Ty<'tcx>
+{
+    let ty = instance.def.def_ty(shared.tcx());
+    monomorphize::apply_param_substs(shared, instance.substs, &ty)
+}
index bf1d9886ae7f0b9eddc5cb52b720181f5686931c..0c3d211912add2498885a63f8b2cda61c15ba02e 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 
+use back::symbol_names;
 use llvm;
 use llvm::{SetUnnamedAddr};
 use llvm::{ValueRef, True};
@@ -24,7 +25,6 @@
 use type_::Type;
 use type_of;
 use rustc::ty;
-use rustc::ty::subst::Substs;
 
 use rustc::hir;
 
@@ -80,12 +80,12 @@ pub fn addr_of(ccx: &CrateContext,
 }
 
 pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
-    let instance = Instance::mono(ccx.shared(), def_id);
+    let instance = Instance::mono(ccx.tcx(), def_id);
     if let Some(&g) = ccx.instances().borrow().get(&instance) {
         return g;
     }
 
-    let ty = common::def_ty(ccx.shared(), def_id, Substs::empty());
+    let ty = common::instance_ty(ccx.shared(), &instance);
     let g = if let Some(id) = ccx.tcx().hir.as_local_node_id(def_id) {
 
         let llty = type_of::type_of(ccx, ty);
@@ -114,7 +114,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
             hir_map::NodeForeignItem(&hir::ForeignItem {
                 ref attrs, span, node: hir::ForeignItemStatic(..), ..
             }) => {
-                let sym = instance.symbol_name(ccx.shared());
+                let sym = symbol_names::symbol_name(instance, ccx.shared());
                 let g = if let Some(name) =
                         attr::first_attr_value_str_by_name(&attrs, "linkage") {
                     // If this is a static with a linkage specified, then we need to handle
@@ -174,7 +174,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
 
         g
     } else {
-        let sym = instance.symbol_name(ccx.shared());
+        let sym = symbol_names::symbol_name(instance, ccx.shared());
 
         // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
         // FIXME(nagisa): investigate whether it can be changed into define_global
@@ -235,7 +235,8 @@ pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             v
         };
 
-        let ty = common::def_ty(ccx.shared(), def_id, Substs::empty());
+        let instance = Instance::mono(ccx.tcx(), def_id);
+        let ty = common::instance_ty(ccx.shared(), &instance);
         let llty = type_of::type_of(ccx, ty);
         let g = if val_llty == llty {
             g
index 52851ea995d4b7c42edd769695931a5fc707a064..1c1395f1b7762604309616c59b07979824036bf8 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::traits;
 use debuginfo;
-use callee::Callee;
+use callee;
 use base;
 use declare;
-use glue::DropGlueKind;
 use monomorphize::Instance;
 
 use partitioning::CodegenUnit;
@@ -46,7 +45,7 @@
 use syntax::ast;
 use syntax::symbol::InternedString;
 use syntax_pos::DUMMY_SP;
-use abi::{Abi, FnType};
+use abi::Abi;
 
 pub struct Stats {
     pub n_glues_created: Cell<usize>,
@@ -94,8 +93,6 @@ pub struct LocalCrateContext<'tcx> {
     previous_work_product: Option<WorkProduct>,
     codegen_unit: CodegenUnit<'tcx>,
     needs_unwind_cleanup_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
-    fn_pointer_shims: RefCell<FxHashMap<Ty<'tcx>, ValueRef>>,
-    drop_glues: RefCell<FxHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
     /// Cache instances of monomorphic and polymorphic items
     instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
     /// Cache generated vtables
@@ -546,16 +543,6 @@ pub fn translation_items(&self) -> &RefCell<FxHashSet<TransItem<'tcx>>> {
         &self.translation_items
     }
 
-    /// Given the def-id of some item that has no type parameters, make
-    /// a suitable "empty substs" for it.
-    pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
-        Substs::for_item(self.tcx(), item_def_id,
-                         |_, _| self.tcx().mk_region(ty::ReErased),
-                         |_, _| {
-            bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
-        })
-    }
-
     pub fn metadata_symbol_name(&self) -> String {
         format!("rust_metadata_{}_{}",
                 self.link_meta().crate_name,
@@ -597,8 +584,6 @@ fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
                 previous_work_product: previous_work_product,
                 codegen_unit: codegen_unit,
                 needs_unwind_cleanup_cache: RefCell::new(FxHashMap()),
-                fn_pointer_shims: RefCell::new(FxHashMap()),
-                drop_glues: RefCell::new(FxHashMap()),
                 instances: RefCell::new(FxHashMap()),
                 vtables: RefCell::new(FxHashMap()),
                 const_cstr_cache: RefCell::new(FxHashMap()),
@@ -733,15 +718,6 @@ pub fn needs_unwind_cleanup_cache(&self) -> &RefCell<FxHashMap<Ty<'tcx>, bool>>
         &self.local().needs_unwind_cleanup_cache
     }
 
-    pub fn fn_pointer_shims(&self) -> &RefCell<FxHashMap<Ty<'tcx>, ValueRef>> {
-        &self.local().fn_pointer_shims
-    }
-
-    pub fn drop_glues<'a>(&'a self)
-                          -> &'a RefCell<FxHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>> {
-        &self.local().drop_glues
-    }
-
     pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> {
         &self.local().instances
     }
@@ -886,7 +862,7 @@ pub fn translation_items(&self) -> &RefCell<FxHashSet<TransItem<'tcx>>> {
     /// Given the def-id of some item that has no type parameters, make
     /// a suitable "empty substs" for it.
     pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
-        self.shared().empty_substs_for_def_id(item_def_id)
+        self.tcx().empty_substs_for_def_id(item_def_id)
     }
 
     /// Generate a new symbol name with the given prefix. This symbol name must
@@ -930,7 +906,7 @@ pub fn eh_personality(&self) -> ValueRef {
         let tcx = self.tcx();
         let llfn = match tcx.lang_items.eh_personality() {
             Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
-                Callee::def(self, def_id, tcx.intern_substs(&[])).reify(self)
+                callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
             }
             _ => {
                 let name = if base::wants_msvc_seh(self.sess()) {
@@ -958,7 +934,7 @@ pub fn eh_unwind_resume(&self) -> ValueRef {
         let tcx = self.tcx();
         assert!(self.sess().target.target.options.custom_unwind_resume);
         if let Some(def_id) = tcx.lang_items.eh_unwind_resume() {
-            let llfn = Callee::def(self, def_id, tcx.intern_substs(&[])).reify(self);
+            let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
             unwresume.set(Some(llfn));
             return llfn;
         }
index 1d4aebf135b9ec1dcf2a459396ae725bc8f62f02..8e86b50b3f7dd7c39e6c23a9df91ed679c64cfaf 100644 (file)
@@ -205,7 +205,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         return FunctionDebugContext::DebugInfoDisabled;
     }
 
-    for attr in cx.tcx().get_attrs(instance.def).iter() {
+    for attr in instance.def.attrs(cx.tcx()).iter() {
         if attr.check_name("no_debug") {
             return FunctionDebugContext::FunctionWithoutDebugInfo;
         }
@@ -229,11 +229,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     };
 
     // Find the enclosing function, in case this is a closure.
-    let def_key = cx.tcx().def_key(instance.def);
+    let def_key = cx.tcx().def_key(instance.def_id());
     let mut name = def_key.disambiguated_data.data.to_string();
     let name_len = name.len();
 
-    let fn_def_id = cx.tcx().closure_base_def_id(instance.def);
+    let fn_def_id = cx.tcx().closure_base_def_id(instance.def_id());
 
     // Get_template_parameters() will append a `<...>` clause to the function
     // name if necessary.
@@ -246,11 +246,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                                       &mut name);
 
     // Build the linkage_name out of the item path and "template" parameters.
-    let linkage_name = mangled_name_of_item(cx, instance.def, &name[name_len..]);
+    let linkage_name = mangled_name_of_item(cx, instance.def_id(), &name[name_len..]);
 
     let scope_line = span_start(cx, span).line;
 
-    let local_id = cx.tcx().hir.as_local_node_id(instance.def);
+    let local_id = cx.tcx().hir.as_local_node_id(instance.def_id());
     let is_local_to_unit = local_id.map_or(false, |id| is_node_local_to_unit(cx, id));
 
     let function_name = CString::new(name).unwrap();
@@ -394,7 +394,7 @@ fn get_containing_scope<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
         // First, let's see if this is a method within an inherent impl. Because
         // if yes, we want to make the result subroutine DIE a child of the
         // subroutine's self-type.
-        let self_type = cx.tcx().impl_of_method(instance.def).and_then(|impl_def_id| {
+        let self_type = cx.tcx().impl_of_method(instance.def_id()).and_then(|impl_def_id| {
             // If the method does *not* belong to a trait, proceed
             if cx.tcx().trait_id_of_impl(impl_def_id).is_none() {
                 let impl_self_ty =
@@ -417,9 +417,9 @@ fn get_containing_scope<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
 
         self_type.unwrap_or_else(|| {
             namespace::item_namespace(cx, DefId {
-                krate: instance.def.krate,
+                krate: instance.def_id().krate,
                 index: cx.tcx()
-                         .def_key(instance.def)
+                         .def_key(instance.def_id())
                          .parent
                          .expect("get_containing_scope: missing parent?")
             })
index 35ebd67b5f8c19f8555d615397b976676d960588..41a9ab2842dcd3e85694b6d25b73f43821fb8c58 100644 (file)
 // Code relating to drop glue.
 
 use std;
-use std::iter;
 
 use llvm;
-use llvm::{ValueRef, get_param};
-use middle::lang_items::BoxFreeFnLangItem;
-use rustc::ty::subst::{Substs};
+use llvm::{ValueRef};
 use rustc::traits;
-use rustc::ty::{self, layout, AdtDef, AdtKind, Ty, TypeFoldable};
-use rustc::ty::subst::Kind;
-use rustc::mir::tcx::LvalueTy;
-use mir::lvalue::LvalueRef;
-use adt;
-use base::*;
-use callee::Callee;
-use cleanup::CleanupScope;
+use rustc::ty::{self, Ty, TypeFoldable};
 use common::*;
 use machine::*;
+use meth;
 use monomorphize;
-use trans_item::TransItem;
-use tvec;
-use type_of::{type_of, sizing_type_of, align_of};
-use type_::Type;
+use type_of::{sizing_type_of, align_of};
 use value::Value;
-use Disr;
 use builder::Builder;
 
-use syntax_pos::DUMMY_SP;
-use mir::lvalue::Alignment;
-
-pub fn trans_exchange_free_ty<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) {
-    let content_ty = ptr.ty.to_ty(bcx.tcx());
-    let def_id = langcall(bcx.tcx(), None, "", BoxFreeFnLangItem);
-    let substs = bcx.tcx().mk_substs(iter::once(Kind::from(content_ty)));
-    let callee = Callee::def(bcx.ccx, def_id, substs);
-
-    let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
-
-    let llret = bcx.call(callee.reify(bcx.ccx),
-        &[ptr.llval, ptr.llextra][..1 + ptr.has_extra() as usize], None);
-    fn_ty.apply_attrs_callsite(llret);
-}
-
-pub fn get_drop_glue_type<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
+pub fn needs_drop_glue<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'tcx>) -> bool {
     assert!(t.is_normalized_for_trans());
 
     let t = scx.tcx().erase_regions(&t);
 
-    // Even if there is no dtor for t, there might be one deeper down and we
-    // might need to pass in the vtable ptr.
-    if !scx.type_is_sized(t) {
-        return t;
-    }
-
     // FIXME (#22815): note that type_needs_drop conservatively
     // approximates in some cases and may say a type expression
     // requires drop glue when it actually does not.
     //
     // (In this case it is not clear whether any harm is done, i.e.
-    // erroneously returning `t` in some cases where we could have
-    // returned `tcx.types.i8` does not appear unsound. The impact on
+    // erroneously returning `true` in some cases where we could have
+    // returned `false` does not appear unsound. The impact on
     // code quality is unknown at this time.)
 
     if !scx.type_needs_drop(t) {
-        return scx.tcx().types.i8;
+        return false;
     }
     match t.sty {
         ty::TyAdt(def, _) if def.is_box() => {
@@ -86,215 +51,19 @@ pub fn get_drop_glue_type<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'t
                     let layout = t.layout(&infcx).unwrap();
                     if layout.size(&scx.tcx().data_layout).bytes() == 0 {
                         // `Box<ZeroSizeType>` does not allocate.
-                        scx.tcx().types.i8
+                        false
                     } else {
-                        t
+                        true
                     }
                 })
             } else {
-                t
+                true
             }
         }
-        _ => t
+        _ => true
     }
 }
 
-fn drop_ty<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, args: LvalueRef<'tcx>) {
-    call_drop_glue(bcx, args, false, None)
-}
-
-pub fn call_drop_glue<'a, 'tcx>(
-    bcx: &Builder<'a, 'tcx>,
-    mut args: LvalueRef<'tcx>,
-    skip_dtor: bool,
-    funclet: Option<&'a Funclet>,
-) {
-    let t = args.ty.to_ty(bcx.tcx());
-    // NB: v is an *alias* of type t here, not a direct value.
-    debug!("call_drop_glue(t={:?}, skip_dtor={})", t, skip_dtor);
-    if bcx.ccx.shared().type_needs_drop(t) {
-        let ccx = bcx.ccx;
-        let g = if skip_dtor {
-            DropGlueKind::TyContents(t)
-        } else {
-            DropGlueKind::Ty(t)
-        };
-        let glue = get_drop_glue_core(ccx, g);
-        let glue_type = get_drop_glue_type(ccx.shared(), t);
-        if glue_type != t {
-            args.llval = bcx.pointercast(args.llval, type_of(ccx, glue_type).ptr_to());
-        }
-
-        // No drop-hint ==> call standard drop glue
-        bcx.call(glue, &[args.llval, args.llextra][..1 + args.has_extra() as usize],
-            funclet.map(|b| b.bundle()));
-    }
-}
-
-pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> ValueRef {
-    get_drop_glue_core(ccx, DropGlueKind::Ty(t))
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum DropGlueKind<'tcx> {
-    /// The normal path; runs the dtor, and then recurs on the contents
-    Ty(Ty<'tcx>),
-    /// Skips the dtor, if any, for ty; drops the contents directly.
-    /// Note that the dtor is only skipped at the most *shallow*
-    /// level, namely, an `impl Drop for Ty` itself. So, for example,
-    /// if Ty is Newtype(S) then only the Drop impl for Newtype itself
-    /// will be skipped, while the Drop impl for S, if any, will be
-    /// invoked.
-    TyContents(Ty<'tcx>),
-}
-
-impl<'tcx> DropGlueKind<'tcx> {
-    pub fn ty(&self) -> Ty<'tcx> {
-        match *self { DropGlueKind::Ty(t) | DropGlueKind::TyContents(t) => t }
-    }
-
-    pub fn map_ty<F>(&self, mut f: F) -> DropGlueKind<'tcx> where F: FnMut(Ty<'tcx>) -> Ty<'tcx>
-    {
-        match *self {
-            DropGlueKind::Ty(t) => DropGlueKind::Ty(f(t)),
-            DropGlueKind::TyContents(t) => DropGlueKind::TyContents(f(t)),
-        }
-    }
-}
-
-fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKind<'tcx>) -> ValueRef {
-    let g = g.map_ty(|t| get_drop_glue_type(ccx.shared(), t));
-    match ccx.drop_glues().borrow().get(&g) {
-        Some(&(glue, _)) => glue,
-        None => {
-            bug!("Could not find drop glue for {:?} -- {} -- {}.",
-                    g,
-                    TransItem::DropGlue(g).to_raw_string(),
-                    ccx.codegen_unit().name());
-        }
-    }
-}
-
-pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKind<'tcx>) {
-    assert_eq!(g.ty(), get_drop_glue_type(ccx.shared(), g.ty()));
-    let (llfn, _) = ccx.drop_glues().borrow().get(&g).unwrap().clone();
-
-    let mut bcx = Builder::new_block(ccx, llfn, "entry-block");
-
-    ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
-    // All glue functions take values passed *by alias*; this is a
-    // requirement since in many contexts glue is invoked indirectly and
-    // the caller has no idea if it's dealing with something that can be
-    // passed by value.
-    //
-    // llfn is expected be declared to take a parameter of the appropriate
-    // type, so we don't need to explicitly cast the function parameter.
-
-    // NB: v0 is an *alias* of type t here, not a direct value.
-    // Only drop the value when it ... well, we used to check for
-    // non-null, (and maybe we need to continue doing so), but we now
-    // must definitely check for special bit-patterns corresponding to
-    // the special dtor markings.
-    let t = g.ty();
-
-    let value = get_param(llfn, 0);
-    let ptr = if ccx.shared().type_is_sized(t) {
-        LvalueRef::new_sized_ty(value, t, Alignment::AbiAligned)
-    } else {
-        LvalueRef::new_unsized_ty(value, get_param(llfn, 1), t, Alignment::AbiAligned)
-    };
-
-    let skip_dtor = match g {
-        DropGlueKind::Ty(_) => false,
-        DropGlueKind::TyContents(_) => true
-    };
-
-    let bcx = match t.sty {
-        ty::TyAdt(def, _) if def.is_box() => {
-            // Support for Box is built-in as yet and its drop glue is special
-            // despite having a dummy Drop impl in the library.
-            assert!(!skip_dtor);
-            let content_ty = t.boxed_ty();
-            let ptr = if !bcx.ccx.shared().type_is_sized(content_ty) {
-                let llbox = bcx.load(get_dataptr(&bcx, ptr.llval), None);
-                let info = bcx.load(get_meta(&bcx, ptr.llval), None);
-                LvalueRef::new_unsized_ty(llbox, info, content_ty, Alignment::AbiAligned)
-            } else {
-                LvalueRef::new_sized_ty(
-                    bcx.load(ptr.llval, None),
-                    content_ty, Alignment::AbiAligned)
-            };
-            drop_ty(&bcx, ptr);
-            trans_exchange_free_ty(&bcx, ptr);
-            bcx
-        }
-        ty::TyDynamic(..) => {
-            // No support in vtable for distinguishing destroying with
-            // versus without calling Drop::drop. Assert caller is
-            // okay with always calling the Drop impl, if any.
-            assert!(!skip_dtor);
-            let dtor = bcx.load(ptr.llextra, None);
-            bcx.call(dtor, &[ptr.llval], None);
-            bcx
-        }
-        ty::TyAdt(def, ..) if def.has_dtor(bcx.tcx()) && !skip_dtor => {
-            let shallow_drop = def.is_union();
-            let tcx = bcx.tcx();
-
-            let def = t.ty_adt_def().unwrap();
-
-            // Be sure to put the contents into a scope so we can use an invoke
-            // instruction to call the user destructor but still call the field
-            // destructors if the user destructor panics.
-            //
-            // FIXME (#14875) panic-in-drop semantics might be unsupported; we
-            // might well consider changing below to more direct code.
-            // Issue #23611: schedule cleanup of contents, re-inspecting the
-            // discriminant (if any) in case of variant swap in drop code.
-            let contents_scope = if !shallow_drop {
-                CleanupScope::schedule_drop_adt_contents(&bcx, ptr)
-            } else {
-                CleanupScope::noop()
-            };
-
-            let trait_ref = ty::Binder(ty::TraitRef {
-                def_id: tcx.lang_items.drop_trait().unwrap(),
-                substs: tcx.mk_substs_trait(t, &[])
-            });
-            let vtbl = match fulfill_obligation(bcx.ccx.shared(), DUMMY_SP, trait_ref) {
-                traits::VtableImpl(data) => data,
-                _ => bug!("dtor for {:?} is not an impl???", t)
-            };
-            let dtor_did = def.destructor(tcx).unwrap().did;
-            let callee = Callee::def(bcx.ccx, dtor_did, vtbl.substs);
-            let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
-            let llret;
-            let args = &[ptr.llval, ptr.llextra][..1 + ptr.has_extra() as usize];
-            if let Some(landing_pad) = contents_scope.landing_pad {
-                let normal_bcx = bcx.build_sibling_block("normal-return");
-                llret = bcx.invoke(callee.reify(ccx), args, normal_bcx.llbb(), landing_pad, None);
-                bcx = normal_bcx;
-            } else {
-                llret = bcx.call(callee.reify(bcx.ccx), args, None);
-            }
-            fn_ty.apply_attrs_callsite(llret);
-            contents_scope.trans(&bcx);
-            bcx
-        }
-        ty::TyAdt(def, ..) if def.is_union() => {
-            bcx
-        }
-        _ => {
-            if bcx.ccx.shared().type_needs_drop(t) {
-                drop_structural_ty(bcx, ptr)
-            } else {
-                bcx
-            }
-        }
-    };
-    bcx.ret_void();
-}
-
 pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef)
                                        -> (ValueRef, ValueRef) {
     debug!("calculate size of DST: {}; with lost info: {:?}",
@@ -381,20 +150,8 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
             (size, align)
         }
         ty::TyDynamic(..) => {
-            // info points to the vtable and the second entry in the vtable is the
-            // dynamic size of the object.
-            let info = bcx.pointercast(info, Type::int(bcx.ccx).ptr_to());
-            let size_ptr = bcx.gepi(info, &[1]);
-            let align_ptr = bcx.gepi(info, &[2]);
-
-            let size = bcx.load(size_ptr, None);
-            let align = bcx.load(align_ptr, None);
-
-            // Vtable loads are invariant
-            bcx.set_invariant_load(size);
-            bcx.set_invariant_load(align);
-
-            (size, align)
+            // load size/align from vtable
+            (meth::SIZE.get_usize(bcx, info), meth::ALIGN.get_usize(bcx, info))
         }
         ty::TySlice(_) | ty::TyStr => {
             let unit_ty = t.sequence_element_type(bcx.tcx());
@@ -409,141 +166,3 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
         _ => bug!("Unexpected unsized type, found {}", t)
     }
 }
-
-// Iterates through the elements of a structural type, dropping them.
-fn drop_structural_ty<'a, 'tcx>(
-    cx: Builder<'a, 'tcx>,
-    mut ptr: LvalueRef<'tcx>
-) -> Builder<'a, 'tcx> {
-    fn iter_variant_fields<'a, 'tcx>(
-        cx: &'a Builder<'a, 'tcx>,
-        av: LvalueRef<'tcx>,
-        adt_def: &'tcx AdtDef,
-        variant_index: usize,
-        substs: &'tcx Substs<'tcx>
-    ) {
-        let variant = &adt_def.variants[variant_index];
-        let tcx = cx.tcx();
-        for (i, field) in variant.fields.iter().enumerate() {
-            let arg = monomorphize::field_ty(tcx, substs, field);
-            let (field_ptr, align) = av.trans_field_ptr(&cx, i);
-            drop_ty(&cx, LvalueRef::new_sized_ty(field_ptr, arg, align));
-        }
-    }
-
-    let mut cx = cx;
-    let t = ptr.ty.to_ty(cx.tcx());
-    match t.sty {
-        ty::TyClosure(def_id, substs) => {
-            for (i, upvar_ty) in substs.upvar_tys(def_id, cx.tcx()).enumerate() {
-                let (llupvar, align) = ptr.trans_field_ptr(&cx, i);
-                drop_ty(&cx, LvalueRef::new_sized_ty(llupvar, upvar_ty, align));
-            }
-        }
-        ty::TyArray(_, n) => {
-            let base = get_dataptr(&cx, ptr.llval);
-            let len = C_uint(cx.ccx, n);
-            let unit_ty = t.sequence_element_type(cx.tcx());
-            cx = tvec::slice_for_each(&cx, base, unit_ty, len,
-                |bb, vv| drop_ty(bb, LvalueRef::new_sized_ty(vv, unit_ty, ptr.alignment)));
-        }
-        ty::TySlice(_) | ty::TyStr => {
-            let unit_ty = t.sequence_element_type(cx.tcx());
-            cx = tvec::slice_for_each(&cx, ptr.llval, unit_ty, ptr.llextra,
-                |bb, vv| drop_ty(bb, LvalueRef::new_sized_ty(vv, unit_ty, ptr.alignment)));
-        }
-        ty::TyTuple(ref args, _) => {
-            for (i, arg) in args.iter().enumerate() {
-                let (llfld_a, align) = ptr.trans_field_ptr(&cx, i);
-                drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg, align));
-            }
-        }
-        ty::TyAdt(adt, substs) => match adt.adt_kind() {
-            AdtKind::Struct => {
-                for (i, field) in adt.variants[0].fields.iter().enumerate() {
-                    let field_ty = monomorphize::field_ty(cx.tcx(), substs, field);
-                    let (llval, align) = ptr.trans_field_ptr(&cx, i);
-                    let field_ptr = if cx.ccx.shared().type_is_sized(field_ty) {
-                        LvalueRef::new_sized_ty(llval, field_ty, align)
-                    } else {
-                        LvalueRef::new_unsized_ty(llval, ptr.llextra, field_ty, align)
-                    };
-                    drop_ty(&cx, field_ptr);
-                }
-            }
-            AdtKind::Union => {
-                bug!("Union in `glue::drop_structural_ty`");
-            }
-            AdtKind::Enum => {
-                let n_variants = adt.variants.len();
-
-                // NB: we must hit the discriminant first so that structural
-                // comparison know not to proceed when the discriminants differ.
-
-                // Obtain a representation of the discriminant sufficient to translate
-                // destructuring; this may or may not involve the actual discriminant.
-                let l = cx.ccx.layout_of(t);
-                match *l {
-                    layout::Univariant { .. } |
-                    layout::UntaggedUnion { .. } => {
-                        if n_variants != 0 {
-                            assert!(n_variants == 1);
-                            ptr.ty = LvalueTy::Downcast {
-                                adt_def: adt,
-                                substs: substs,
-                                variant_index: 0,
-                            };
-                            iter_variant_fields(&cx, ptr, &adt, 0, substs);
-                        }
-                    }
-                    layout::CEnum { .. } |
-                    layout::General { .. } |
-                    layout::RawNullablePointer { .. } |
-                    layout::StructWrappedNullablePointer { .. } => {
-                        let lldiscrim_a = adt::trans_get_discr(
-                            &cx, t, ptr.llval, ptr.alignment, None, false);
-
-                        // Create a fall-through basic block for the "else" case of
-                        // the switch instruction we're about to generate. Note that
-                        // we do **not** use an Unreachable instruction here, even
-                        // though most of the time this basic block will never be hit.
-                        //
-                        // When an enum is dropped it's contents are currently
-                        // overwritten to DTOR_DONE, which means the discriminant
-                        // could have changed value to something not within the actual
-                        // range of the discriminant. Currently this function is only
-                        // used for drop glue so in this case we just return quickly
-                        // from the outer function, and any other use case will only
-                        // call this for an already-valid enum in which case the `ret
-                        // void` will never be hit.
-                        let ret_void_cx = cx.build_sibling_block("enum-iter-ret-void");
-                        ret_void_cx.ret_void();
-                        let llswitch = cx.switch(lldiscrim_a, ret_void_cx.llbb(), n_variants);
-                        let next_cx = cx.build_sibling_block("enum-iter-next");
-
-                        for (i, discr) in adt.discriminants(cx.tcx()).enumerate() {
-                            let variant_cx_name = format!("enum-iter-variant-{}", i);
-                            let variant_cx = cx.build_sibling_block(&variant_cx_name);
-                            let case_val = adt::trans_case(&cx, t, Disr::from(discr));
-                            variant_cx.add_case(llswitch, case_val, variant_cx.llbb());
-                            ptr.ty = LvalueTy::Downcast {
-                                adt_def: adt,
-                                substs: substs,
-                                variant_index: i,
-                            };
-                            iter_variant_fields(&variant_cx, ptr, &adt, i, substs);
-                            variant_cx.br(next_cx.llbb());
-                        }
-                        cx = next_cx;
-                    }
-                    _ => bug!("{} is not an enum.", t),
-                }
-            }
-        },
-
-        _ => {
-            cx.sess().unimpl(&format!("type in drop_structural_ty: {}", t))
-        }
-    }
-    return cx;
-}
index b7aedb742db02e676e7ccb9d1bbb4563fa8652e6..762bf8592ffccf83049d8804013b8d00f437141d 100644 (file)
@@ -261,7 +261,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
         "ctlz" | "cttz" | "ctpop" | "bswap" |
         "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
         "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
-        "unchecked_div" | "unchecked_rem" => {
+        "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => {
             let sty = &arg_tys[0].sty;
             match int_type_width_signed(sty, ccx) {
                 Some((width, signed)) =>
@@ -311,6 +311,13 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
                             } else {
                                 bcx.urem(llargs[0], llargs[1])
                             },
+                        "unchecked_shl" => bcx.shl(llargs[0], llargs[1]),
+                        "unchecked_shr" =>
+                            if signed {
+                                bcx.ashr(llargs[0], llargs[1])
+                            } else {
+                                bcx.lshr(llargs[0], llargs[1])
+                            },
                         _ => bug!(),
                     },
                 None => {
index 1530fcda3d3ea19c5415d17983fd47220de6928a..f3e30ed4839ae488fe1aeb86cce9d89bfa3e58c0 100644 (file)
@@ -28,6 +28,7 @@
 #![feature(box_syntax)]
 #![feature(const_fn)]
 #![feature(custom_attribute)]
+#![cfg_attr(stage0, feature(field_init_shorthand))]
 #![allow(unused_attributes)]
 #![feature(i128_type)]
 #![feature(libc)]
@@ -112,7 +113,6 @@ pub mod back {
 mod cabi_x86_64;
 mod cabi_x86_win64;
 mod callee;
-mod cleanup;
 mod collector;
 mod common;
 mod consts;
index a3f4168e96f2a0c5e2bdc13d824a0846e34c7a5b..75ab407614050eab3e187c868b020627569245cf 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use attributes;
-use llvm::{ValueRef, get_params};
+use llvm::ValueRef;
 use rustc::traits;
-use callee::{Callee, CalleeData};
+use callee;
 use common::*;
 use builder::Builder;
 use consts;
-use declare;
-use glue;
 use machine;
-use monomorphize::Instance;
+use monomorphize;
 use type_::Type;
 use type_of::*;
 use value::Value;
 use rustc::ty;
 
-// drop_glue pointer, size, align.
-const VTABLE_OFFSET: usize = 3;
-
-/// Extracts a method from a trait object's vtable, at the specified index.
-pub fn get_virtual_method<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
-                                    llvtable: ValueRef,
-                                    vtable_index: usize) -> ValueRef {
-    // Load the data pointer from the object.
-    debug!("get_virtual_method(vtable_index={}, llvtable={:?})",
-           vtable_index, Value(llvtable));
-
-    let ptr = bcx.load_nonnull(bcx.gepi(llvtable, &[vtable_index + VTABLE_OFFSET]), None);
-    // Vtable loads are invariant
-    bcx.set_invariant_load(ptr);
-    ptr
-}
+#[derive(Copy, Clone, Debug)]
+pub struct VirtualIndex(usize);
 
-/// Generate a shim function that allows an object type like `SomeTrait` to
-/// implement the type `SomeTrait`. Imagine a trait definition:
-///
-///    trait SomeTrait { fn get(&self) -> i32; ... }
-///
-/// And a generic bit of code:
-///
-///    fn foo<T:SomeTrait>(t: &T) {
-///        let x = SomeTrait::get;
-///        x(t)
-///    }
-///
-/// What is the value of `x` when `foo` is invoked with `T=SomeTrait`?
-/// The answer is that it is a shim function generated by this routine:
-///
-///    fn shim(t: &SomeTrait) -> i32 {
-///        // ... call t.get() virtually ...
-///    }
-///
-/// In fact, all virtual calls can be thought of as normal trait calls
-/// that go through this shim function.
-pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
-                                   callee: Callee<'tcx>)
-                                   -> ValueRef {
-    debug!("trans_object_shim({:?})", callee);
-
-    let function_name = match callee.ty.sty {
-        ty::TyFnDef(def_id, substs, _) => {
-            let instance = Instance::new(def_id, substs);
-            instance.symbol_name(ccx.shared())
-        }
-        _ => bug!()
-    };
-
-    let llfn = declare::define_internal_fn(ccx, &function_name, callee.ty);
-    attributes::set_frame_pointer_elimination(ccx, llfn);
-
-    let bcx = Builder::new_block(ccx, llfn, "entry-block");
-
-    let mut llargs = get_params(llfn);
-    let fn_ret = callee.ty.fn_ret();
-    let fn_ty = callee.direct_fn_type(ccx, &[]);
-
-    let fn_ptr = match callee.data {
-        CalleeData::Virtual(idx) => {
-            let fn_ptr = get_virtual_method(&bcx,
-                llargs.remove(fn_ty.ret.is_indirect() as usize + 1), idx);
-            let llty = fn_ty.llvm_type(bcx.ccx).ptr_to();
-            bcx.pointercast(fn_ptr, llty)
-        },
-        _ => bug!("trans_object_shim called with non-virtual callee"),
-    };
-    let llret = bcx.call(fn_ptr, &llargs, None);
-    fn_ty.apply_attrs_callsite(llret);
-
-    if fn_ret.0.is_never() {
-        bcx.unreachable();
-    } else {
-        if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
-            bcx.ret_void();
-        } else {
-            bcx.ret(llret);
-        }
+pub const DESTRUCTOR: VirtualIndex = VirtualIndex(0);
+pub const SIZE: VirtualIndex = VirtualIndex(1);
+pub const ALIGN: VirtualIndex = VirtualIndex(2);
+
+impl<'a, 'tcx> VirtualIndex {
+    pub fn from_index(index: usize) -> Self {
+        VirtualIndex(index + 3)
+    }
+
+    pub fn get_fn(self, bcx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef {
+        // Load the data pointer from the object.
+        debug!("get_fn({:?}, {:?})", Value(llvtable), self);
+
+        let ptr = bcx.load_nonnull(bcx.gepi(llvtable, &[self.0]), None);
+        // Vtable loads are invariant
+        bcx.set_invariant_load(ptr);
+        ptr
     }
 
-    llfn
+    pub fn get_usize(self, bcx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef {
+        // Load the data pointer from the object.
+        debug!("get_int({:?}, {:?})", Value(llvtable), self);
+
+        let llvtable = bcx.pointercast(llvtable, Type::int(bcx.ccx).ptr_to());
+        let ptr = bcx.load(bcx.gepi(llvtable, &[self.0]), None);
+        // Vtable loads are invariant
+        bcx.set_invariant_load(ptr);
+        ptr
+    }
 }
 
 /// Creates a dynamic vtable for the given type and vtable origin.
@@ -139,8 +85,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let align = align_of(ccx, ty);
 
     let mut components: Vec<_> = [
-        // Generate a destructor for the vtable.
-        glue::get_drop_glue(ccx, ty),
+        callee::get_fn(ccx, monomorphize::resolve_drop_in_place(ccx.shared(), ty)),
         C_uint(ccx, size),
         C_uint(ccx, align)
     ].iter().cloned().collect();
@@ -149,7 +94,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         let trait_ref = trait_ref.with_self_ty(tcx, ty);
         let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| {
             opt_mth.map_or(nullptr, |(def_id, substs)| {
-                Callee::def(ccx, def_id, substs).reify(ccx)
+                callee::resolve_and_get_fn(ccx, def_id, substs)
             })
         });
         components.extend(methods);
index 9d40419d338b8a50b2a2f5322b897dd61314885b..226d40948c4dc41096e482f3571954aec8319f0a 100644 (file)
 use rustc::mir;
 use abi::{Abi, FnType, ArgType};
 use base::{self, Lifetime};
-use callee::{Callee, CalleeData, Fn, Intrinsic, NamedTupleConstructor, Virtual};
+use callee;
 use builder::Builder;
 use common::{self, Funclet};
-use common::{C_bool, C_str_slice, C_struct, C_u32, C_undef};
+use common::{C_bool, C_str_slice, C_struct, C_u32, C_uint, C_undef};
 use consts;
 use machine::llalign_of_min;
 use meth;
+use monomorphize;
+use tvec;
 use type_of::{self, align_of};
-use glue;
 use type_::Type;
 
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -208,21 +209,49 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
             mir::TerminatorKind::Drop { ref location, target, unwind } => {
                 let ty = location.ty(&self.mir, bcx.tcx()).to_ty(bcx.tcx());
                 let ty = self.monomorphize(&ty);
+                let drop_fn = monomorphize::resolve_drop_in_place(bcx.ccx.shared(), ty);
 
-                // Double check for necessity to drop
-                if !bcx.ccx.shared().type_needs_drop(ty) {
+                if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
+                    // we don't actually need to drop anything.
                     funclet_br(self, bcx, target);
-                    return;
+                    return
                 }
 
-                let mut lvalue = self.trans_lvalue(&bcx, location);
-                let drop_fn = glue::get_drop_glue(bcx.ccx, ty);
-                let drop_ty = glue::get_drop_glue_type(bcx.ccx.shared(), ty);
-                if bcx.ccx.shared().type_is_sized(ty) && drop_ty != ty {
-                    lvalue.llval = bcx.pointercast(
-                        lvalue.llval, type_of::type_of(bcx.ccx, drop_ty).ptr_to());
-                }
-                let args = &[lvalue.llval, lvalue.llextra][..1 + lvalue.has_extra() as usize];
+                let lvalue = self.trans_lvalue(&bcx, location);
+                let (drop_fn, need_extra) = match ty.sty {
+                    ty::TyDynamic(..) => (meth::DESTRUCTOR.get_fn(&bcx, lvalue.llextra),
+                                          false),
+                    ty::TyArray(ety, _) | ty::TySlice(ety) => {
+                        // FIXME: handle panics
+                        let drop_fn = monomorphize::resolve_drop_in_place(
+                            bcx.ccx.shared(), ety);
+                        let drop_fn = callee::get_fn(bcx.ccx, drop_fn);
+                        let bcx = tvec::slice_for_each(
+                            &bcx,
+                            lvalue.project_index(&bcx, C_uint(bcx.ccx, 0u64)),
+                            ety,
+                            lvalue.len(bcx.ccx),
+                            |bcx, llval, loop_bb| {
+                                self.set_debug_loc(&bcx, terminator.source_info);
+                                if let Some(unwind) = unwind {
+                                    bcx.invoke(
+                                        drop_fn,
+                                        &[llval],
+                                        loop_bb,
+                                        llblock(self, unwind),
+                                        cleanup_bundle
+                                    );
+                                } else {
+                                    bcx.call(drop_fn, &[llval], cleanup_bundle);
+                                    bcx.br(loop_bb);
+                                }
+                            });
+                        funclet_br(self, bcx, target);
+                        return
+                    }
+                    _ => (callee::get_fn(bcx.ccx, drop_fn), lvalue.has_extra())
+                };
+                let args = &[lvalue.llval, lvalue.llextra][..1 + need_extra as usize];
                 if let Some(unwind) = unwind {
                     bcx.invoke(
                         drop_fn,
@@ -340,9 +369,8 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
 
                 // Obtain the panic entry point.
                 let def_id = common::langcall(bcx.tcx(), Some(span), "", lang_item);
-                let callee = Callee::def(bcx.ccx, def_id,
-                    bcx.ccx.empty_substs_for_def_id(def_id));
-                let llfn = callee.reify(bcx.ccx);
+                let instance = ty::Instance::mono(bcx.tcx(), def_id);
+                let llfn = callee::get_fn(bcx.ccx, instance);
 
                 // Translate the actual panic invoke/call.
                 if let Some(unwind) = cleanup {
@@ -365,30 +393,30 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
                 // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
                 let callee = self.trans_operand(&bcx, func);
 
-                let (mut callee, sig) = match callee.ty.sty {
+                let (instance, mut llfn, sig) = match callee.ty.sty {
                     ty::TyFnDef(def_id, substs, sig) => {
-                        (Callee::def(bcx.ccx, def_id, substs), sig)
+                        (Some(monomorphize::resolve(bcx.ccx.shared(), def_id, substs)),
+                         None,
+                         sig)
                     }
                     ty::TyFnPtr(sig) => {
-                        (Callee {
-                            data: Fn(callee.immediate()),
-                            ty: callee.ty
-                        }, sig)
+                        (None,
+                         Some(callee.immediate()),
+                         sig)
                     }
                     _ => bug!("{} is not callable", callee.ty)
                 };
-
+                let def = instance.map(|i| i.def);
                 let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
                 let abi = sig.abi;
 
                 // Handle intrinsics old trans wants Expr's for, ourselves.
-                let intrinsic = match (&callee.ty.sty, &callee.data) {
-                    (&ty::TyFnDef(def_id, ..), &Intrinsic) => {
-                        Some(bcx.tcx().item_name(def_id).as_str())
-                    }
+                let intrinsic = match def {
+                    Some(ty::InstanceDef::Intrinsic(def_id))
+                        => Some(bcx.tcx().item_name(def_id).as_str()),
                     _ => None
                 };
-                let mut intrinsic = intrinsic.as_ref().map(|s| &s[..]);
+                let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
 
                 if intrinsic == Some("move_val_init") {
                     let &(_, target) = destination.as_ref().unwrap();
@@ -412,27 +440,19 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
                     let op_ty = op_arg.ty(&self.mir, bcx.tcx());
                     self.monomorphize(&op_ty)
                 }).collect::<Vec<_>>();
-                let fn_ty = callee.direct_fn_type(bcx.ccx, &extra_args);
-
-                if intrinsic == Some("drop_in_place") {
-                    let &(_, target) = destination.as_ref().unwrap();
-                    let ty = if let ty::TyFnDef(_, substs, _) = callee.ty.sty {
-                        substs.type_at(0)
-                    } else {
-                        bug!("Unexpected ty: {}", callee.ty);
-                    };
 
-                    // Double check for necessity to drop
-                    if !bcx.ccx.shared().type_needs_drop(ty) {
+                let fn_ty = match def {
+                    Some(ty::InstanceDef::Virtual(..)) => {
+                        FnType::new_vtable(bcx.ccx, sig, &extra_args)
+                    }
+                    Some(ty::InstanceDef::DropGlue(_, None)) => {
+                        // empty drop glue - a nop.
+                        let &(_, target) = destination.as_ref().unwrap();
                         funclet_br(self, bcx, target);
                         return;
                     }
-
-                    let drop_fn = glue::get_drop_glue(bcx.ccx, ty);
-                    let llty = fn_ty.llvm_type(bcx.ccx).ptr_to();
-                    callee.data = Fn(bcx.pointercast(drop_fn, llty));
-                    intrinsic = None;
-                }
+                    _ => FnType::new(bcx.ccx, sig, &extra_args)
+                };
 
                 // The arguments we'll be passing. Plus one to account for outptr, if used.
                 let arg_count = fn_ty.args.len() + fn_ty.ret.is_indirect() as usize;
@@ -440,12 +460,9 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
 
                 // Prepare the return value destination
                 let ret_dest = if let Some((ref dest, _)) = *destination {
-                    let is_intrinsic = if let Intrinsic = callee.data {
-                        true
-                    } else {
-                        false
-                    };
-                    self.make_return_dest(&bcx, dest, &fn_ty.ret, &mut llargs, is_intrinsic)
+                    let is_intrinsic = intrinsic.is_some();
+                    self.make_return_dest(&bcx, dest, &fn_ty.ret, &mut llargs,
+                                          is_intrinsic)
                 } else {
                     ReturnDest::Nothing
                 };
@@ -483,56 +500,56 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
 
                     let op = self.trans_operand(&bcx, arg);
                     self.trans_argument(&bcx, op, &mut llargs, &fn_ty,
-                                        &mut idx, &mut callee.data);
+                                        &mut idx, &mut llfn, &def);
                 }
                 if let Some(tup) = untuple {
                     self.trans_arguments_untupled(&bcx, tup, &mut llargs, &fn_ty,
-                                                  &mut idx, &mut callee.data)
+                                                  &mut idx, &mut llfn, &def)
                 }
 
-                let fn_ptr = match callee.data {
-                    NamedTupleConstructor(_) => {
-                        // FIXME translate this like mir::Rvalue::Aggregate.
-                        callee.reify(bcx.ccx)
-                    }
-                    Intrinsic => {
-                        use intrinsic::trans_intrinsic_call;
-
-                        let (dest, llargs) = match ret_dest {
-                            _ if fn_ty.ret.is_indirect() => {
-                                (llargs[0], &llargs[1..])
-                            }
-                            ReturnDest::Nothing => {
-                                (C_undef(fn_ty.ret.original_ty.ptr_to()), &llargs[..])
-                            }
-                            ReturnDest::IndirectOperand(dst, _) |
-                            ReturnDest::Store(dst) => (dst, &llargs[..]),
-                            ReturnDest::DirectOperand(_) =>
-                                bug!("Cannot use direct operand with an intrinsic call")
-                        };
-
-                        trans_intrinsic_call(&bcx, callee.ty, &fn_ty, &llargs, dest,
-                            terminator.source_info.span);
+                if intrinsic.is_some() && intrinsic != Some("drop_in_place") {
+                    use intrinsic::trans_intrinsic_call;
 
-                        if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
-                            // Make a fake operand for store_return
-                            let op = OperandRef {
-                                val: Ref(dst, Alignment::AbiAligned),
-                                ty: sig.output(),
-                            };
-                            self.store_return(&bcx, ret_dest, fn_ty.ret, op);
+                    let (dest, llargs) = match ret_dest {
+                        _ if fn_ty.ret.is_indirect() => {
+                            (llargs[0], &llargs[1..])
                         }
-
-                        if let Some((_, target)) = *destination {
-                            funclet_br(self, bcx, target);
-                        } else {
-                            bcx.unreachable();
+                        ReturnDest::Nothing => {
+                            (C_undef(fn_ty.ret.original_ty.ptr_to()), &llargs[..])
                         }
+                        ReturnDest::IndirectOperand(dst, _) |
+                        ReturnDest::Store(dst) => (dst, &llargs[..]),
+                        ReturnDest::DirectOperand(_) =>
+                            bug!("Cannot use direct operand with an intrinsic call")
+                    };
 
-                        return;
+                    let callee_ty = common::instance_ty(
+                        bcx.ccx.shared(), instance.as_ref().unwrap());
+                    trans_intrinsic_call(&bcx, callee_ty, &fn_ty, &llargs, dest,
+                                         terminator.source_info.span);
+
+                    if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
+                        // Make a fake operand for store_return
+                        let op = OperandRef {
+                            val: Ref(dst, Alignment::AbiAligned),
+                            ty: sig.output(),
+                        };
+                        self.store_return(&bcx, ret_dest, fn_ty.ret, op);
+                    }
+
+                    if let Some((_, target)) = *destination {
+                        funclet_br(self, bcx, target);
+                    } else {
+                        bcx.unreachable();
                     }
-                    Fn(f) => f,
-                    Virtual(_) => bug!("Virtual fn ptr not extracted")
+
+                    return;
+                }
+
+                let fn_ptr = match (llfn, instance) {
+                    (Some(llfn), _) => llfn,
+                    (None, Some(instance)) => callee::get_fn(bcx.ccx, instance),
+                    _ => span_bug!(span, "no llfn for call"),
                 };
 
                 // Many different ways to call a function handled here
@@ -582,16 +599,17 @@ fn trans_argument(&mut self,
                       llargs: &mut Vec<ValueRef>,
                       fn_ty: &FnType,
                       next_idx: &mut usize,
-                      callee: &mut CalleeData) {
+                      llfn: &mut Option<ValueRef>,
+                      def: &Option<ty::InstanceDef<'tcx>>) {
         if let Pair(a, b) = op.val {
             // Treat the values in a fat pointer separately.
             if common::type_is_fat_ptr(bcx.ccx, op.ty) {
                 let (ptr, meta) = (a, b);
                 if *next_idx == 0 {
-                    if let Virtual(idx) = *callee {
-                        let llfn = meth::get_virtual_method(bcx, meta, idx);
+                    if let Some(ty::InstanceDef::Virtual(_, idx)) = *def {
+                        let llmeth = meth::VirtualIndex::from_index(idx).get_fn(bcx, meta);
                         let llty = fn_ty.llvm_type(bcx.ccx).ptr_to();
-                        *callee = Fn(bcx.pointercast(llfn, llty));
+                        *llfn = Some(bcx.pointercast(llmeth, llty));
                     }
                 }
 
@@ -600,8 +618,8 @@ fn trans_argument(&mut self,
                     // We won't be checking the type again.
                     ty: bcx.tcx().types.err
                 };
-                self.trans_argument(bcx, imm_op(ptr), llargs, fn_ty, next_idx, callee);
-                self.trans_argument(bcx, imm_op(meta), llargs, fn_ty, next_idx, callee);
+                self.trans_argument(bcx, imm_op(ptr), llargs, fn_ty, next_idx, llfn, def);
+                self.trans_argument(bcx, imm_op(meta), llargs, fn_ty, next_idx, llfn, def);
                 return;
             }
         }
@@ -664,7 +682,8 @@ fn trans_arguments_untupled(&mut self,
                                 llargs: &mut Vec<ValueRef>,
                                 fn_ty: &FnType,
                                 next_idx: &mut usize,
-                                callee: &mut CalleeData) {
+                                llfn: &mut Option<ValueRef>,
+                                def: &Option<ty::InstanceDef<'tcx>>) {
         let tuple = self.trans_operand(bcx, operand);
 
         let arg_types = match tuple.ty.sty {
@@ -690,7 +709,7 @@ fn trans_arguments_untupled(&mut self,
                         val: val,
                         ty: ty
                     };
-                    self.trans_argument(bcx, op, llargs, fn_ty, next_idx, callee);
+                    self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def);
                 }
 
             }
@@ -712,7 +731,7 @@ fn trans_arguments_untupled(&mut self,
                         val: Immediate(elem),
                         ty: ty
                     };
-                    self.trans_argument(bcx, op, llargs, fn_ty, next_idx, callee);
+                    self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def);
                 }
             }
             Pair(a, b) => {
@@ -728,7 +747,7 @@ fn trans_arguments_untupled(&mut self,
                         val: Immediate(elem),
                         ty: ty
                     };
-                    self.trans_argument(bcx, op, llargs, fn_ty, next_idx, callee);
+                    self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def);
                 }
             }
         }
@@ -756,14 +775,18 @@ fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> BasicBlockRef {
             return block;
         }
 
+        let block = self.blocks[target_bb];
+        let landing_pad = self.landing_pad_uncached(block);
+        self.landing_pads[target_bb] = Some(landing_pad);
+        landing_pad
+    }
+
+    fn landing_pad_uncached(&mut self, target_bb: BasicBlockRef) -> BasicBlockRef {
         if base::wants_msvc_seh(self.ccx.sess()) {
-            return self.blocks[target_bb];
+            return target_bb;
         }
 
-        let target = self.get_builder(target_bb);
-
         let bcx = self.new_block("cleanup");
-        self.landing_pads[target_bb] = Some(bcx.llbb());
 
         let ccx = bcx.ccx;
         let llpersonality = self.ccx.eh_personality();
@@ -772,7 +795,7 @@ fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> BasicBlockRef {
         bcx.set_cleanup(llretval);
         let slot = self.get_personality_slot(&bcx);
         bcx.store(llretval, slot, None);
-        bcx.br(target.llbb());
+        bcx.br(target_bb);
         bcx.llbb()
     }
 
index b6fcc990344cebbb15fbd04d952c98427af8f6c3..107b0982af982b9d606927696c18677d568db207 100644 (file)
 use rustc::ty::subst::{Kind, Substs, Subst};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use {abi, adt, base, Disr, machine};
-use callee::Callee;
+use callee;
 use builder::Builder;
 use common::{self, CrateContext, const_get_elt, val_ty};
 use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral, C_big_integral};
 use common::{C_null, C_struct, C_str_slice, C_undef, C_uint, C_vector, is_undef};
 use common::const_to_opt_u128;
 use consts;
-use monomorphize::{self, Instance};
+use monomorphize;
 use type_of;
 use type_::Type;
 use value::Value;
@@ -245,11 +245,12 @@ fn new(ccx: &'a CrateContext<'a, 'tcx>,
     }
 
     fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
-                 instance: Instance<'tcx>,
+                 def_id: DefId,
+                 substs: &'tcx Substs<'tcx>,
                  args: IndexVec<mir::Local, Const<'tcx>>)
                  -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
-        let instance = instance.resolve_const(ccx.shared());
-        let mir = ccx.tcx().item_mir(instance.def);
+        let instance = monomorphize::resolve(ccx.shared(), def_id, substs);
+        let mir = ccx.tcx().instance_mir(instance.def);
         MirConstContext::new(ccx, &mir, instance.substs, args).trans()
     }
 
@@ -332,10 +333,8 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
                 mir::TerminatorKind::Call { ref func, ref args, ref destination, .. } => {
                     let fn_ty = func.ty(self.mir, tcx);
                     let fn_ty = self.monomorphize(&fn_ty);
-                    let instance = match fn_ty.sty {
-                        ty::TyFnDef(def_id, substs, _) => {
-                            Instance::new(def_id, substs)
-                        }
+                    let (def_id, substs) = match fn_ty.sty {
+                        ty::TyFnDef(def_id, substs, _) => (def_id, substs),
                         _ => span_bug!(span, "calling {:?} (of type {}) in constant",
                                        func, fn_ty)
                     };
@@ -348,7 +347,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
                         }
                     }
                     if let Some((ref dest, target)) = *destination {
-                        match MirConstContext::trans_def(self.ccx, instance, const_args) {
+                        match MirConstContext::trans_def(self.ccx, def_id, substs, const_args) {
                             Ok(value) => self.store(dest, value, span),
                             Err(err) => if failure.is_ok() { failure = Err(err); }
                         }
@@ -485,8 +484,7 @@ fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span)
                         }
 
                         let substs = self.monomorphize(&substs);
-                        let instance = Instance::new(def_id, substs);
-                        MirConstContext::trans_def(self.ccx, instance, IndexVec::new())
+                        MirConstContext::trans_def(self.ccx, def_id, substs, IndexVec::new())
                     }
                     mir::Literal::Promoted { index } => {
                         let mir = &self.mir.promoted[index];
@@ -567,8 +565,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                     mir::CastKind::ReifyFnPointer => {
                         match operand.ty.sty {
                             ty::TyFnDef(def_id, substs, _) => {
-                                Callee::def(self.ccx, def_id, substs)
-                                    .reify(self.ccx)
+                                callee::resolve_and_get_fn(self.ccx, def_id, substs)
                             }
                             _ => {
                                 span_bug!(span, "{} cannot be reified to a fn ptr",
@@ -588,10 +585,10 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                                 // Now create its substs [Closure, Tuple]
                                 let input = tcx.closure_type(def_id)
                                     .subst(tcx, substs.substs).input(0);
-                                let substs = tcx.mk_substs([operand.ty, input.skip_binder()]
+                                let input = tcx.erase_late_bound_regions_and_normalize(&input);
+                                let substs = tcx.mk_substs([operand.ty, input]
                                     .iter().cloned().map(Kind::from));
-                                Callee::def(self.ccx, call_once, substs)
-                                    .reify(self.ccx)
+                                callee::resolve_and_get_fn(self.ccx, call_once, substs)
                             }
                             _ => {
                                 bug!("{} cannot be cast to a fn ptr", operand.ty)
@@ -935,8 +932,7 @@ pub fn trans_constant(&mut self,
                 }
 
                 let substs = self.monomorphize(&substs);
-                let instance = Instance::new(def_id, substs);
-                MirConstContext::trans_def(bcx.ccx, instance, IndexVec::new())
+                MirConstContext::trans_def(bcx.ccx, def_id, substs, IndexVec::new())
             }
             mir::Literal::Promoted { index } => {
                 let mir = &self.mir.promoted[index];
@@ -964,8 +960,8 @@ pub fn trans_static_initializer<'a, 'tcx>(
     def_id: DefId)
     -> Result<ValueRef, ConstEvalErr<'tcx>>
 {
-    let instance = Instance::mono(ccx.shared(), def_id);
-    MirConstContext::trans_def(ccx, instance, IndexVec::new()).map(|c| c.llval)
+    MirConstContext::trans_def(ccx, def_id, Substs::empty(), IndexVec::new())
+        .map(|c| c.llval)
 }
 
 /// Construct a constant value, suitable for initializing a
index 49e1e3855571b6bcf9f6fe9ea9f35c96dee97112..dd8c1d0e1f0310d5b49d15b2593c03f0b454aacd 100644 (file)
@@ -27,7 +27,6 @@
 use std::ops;
 
 use super::{MirContext, LocalRef};
-use super::operand::OperandValue;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum Alignment {
@@ -95,16 +94,6 @@ pub fn new_sized_ty(llval: ValueRef, ty: Ty<'tcx>, alignment: Alignment) -> Lval
         LvalueRef::new_sized(llval, LvalueTy::from_ty(ty), alignment)
     }
 
-    pub fn new_unsized_ty(llval: ValueRef, llextra: ValueRef, ty: Ty<'tcx>, alignment: Alignment)
-                          -> LvalueRef<'tcx> {
-        LvalueRef {
-            llval: llval,
-            llextra: llextra,
-            ty: LvalueTy::from_ty(ty),
-            alignment: alignment,
-        }
-    }
-
     pub fn alloca(bcx: &Builder<'a, 'tcx>, ty: Ty<'tcx>, name: &str) -> LvalueRef<'tcx> {
         debug!("alloca({:?}: {:?})", name, ty);
         let tmp = bcx.alloca(type_of::type_of(bcx.ccx, ty), name);
@@ -279,6 +268,16 @@ pub fn trans_field_ptr(self, bcx: &Builder<'a, 'tcx>, ix: usize) -> (ValueRef, A
             _ => bug!("element access in type without elements: {} represented as {:#?}", t, l)
         }
     }
+
+    pub fn project_index(&self, bcx: &Builder<'a, 'tcx>, llindex: ValueRef) -> ValueRef {
+        if let ty::TySlice(_) = self.ty.to_ty(bcx.tcx()).sty {
+            // Slices already point to the array element type.
+            bcx.inbounds_gep(self.llval, &[llindex])
+        } else {
+            let zero = common::C_uint(bcx.ccx, 0u64);
+            bcx.inbounds_gep(self.llval, &[zero, llindex])
+        }
+    }
 }
 
 impl<'a, 'tcx> MirContext<'a, 'tcx> {
@@ -314,21 +313,7 @@ pub fn trans_lvalue(&mut self,
                 elem: mir::ProjectionElem::Deref
             }) => {
                 // Load the pointer from its location.
-                let ptr = self.trans_consume(bcx, base);
-                let projected_ty = LvalueTy::from_ty(ptr.ty)
-                    .projection_ty(tcx, &mir::ProjectionElem::Deref);
-                let projected_ty = self.monomorphize(&projected_ty);
-                let (llptr, llextra) = match ptr.val {
-                    OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()),
-                    OperandValue::Pair(llptr, llextra) => (llptr, llextra),
-                    OperandValue::Ref(..) => bug!("Deref of by-Ref type {:?}", ptr.ty)
-                };
-                LvalueRef {
-                    llval: llptr,
-                    llextra: llextra,
-                    ty: projected_ty,
-                    alignment: Alignment::AbiAligned,
-                }
+                self.trans_consume(bcx, base).deref()
             }
             mir::Lvalue::Projection(ref projection) => {
                 let tr_base = self.trans_lvalue(bcx, &projection.base);
@@ -336,17 +321,6 @@ pub fn trans_lvalue(&mut self,
                 let projected_ty = self.monomorphize(&projected_ty);
                 let align = tr_base.alignment;
 
-                let project_index = |llindex| {
-                    let element = if let ty::TySlice(_) = tr_base.ty.to_ty(tcx).sty {
-                        // Slices already point to the array element type.
-                        bcx.inbounds_gep(tr_base.llval, &[llindex])
-                    } else {
-                        let zero = common::C_uint(bcx.ccx, 0u64);
-                        bcx.inbounds_gep(tr_base.llval, &[zero, llindex])
-                    };
-                    (element, align)
-                };
-
                 let ((llprojected, align), llextra) = match projection.elem {
                     mir::ProjectionElem::Deref => bug!(),
                     mir::ProjectionElem::Field(ref field, _) => {
@@ -359,13 +333,14 @@ pub fn trans_lvalue(&mut self,
                     }
                     mir::ProjectionElem::Index(ref index) => {
                         let index = self.trans_operand(bcx, index);
-                        (project_index(self.prepare_index(bcx, index.immediate())), ptr::null_mut())
+                        let llindex = self.prepare_index(bcx, index.immediate());
+                        ((tr_base.project_index(bcx, llindex), align), ptr::null_mut())
                     }
                     mir::ProjectionElem::ConstantIndex { offset,
                                                          from_end: false,
                                                          min_length: _ } => {
                         let lloffset = C_uint(bcx.ccx, offset);
-                        (project_index(lloffset), ptr::null_mut())
+                        ((tr_base.project_index(bcx, lloffset), align), ptr::null_mut())
                     }
                     mir::ProjectionElem::ConstantIndex { offset,
                                                          from_end: true,
@@ -373,11 +348,10 @@ pub fn trans_lvalue(&mut self,
                         let lloffset = C_uint(bcx.ccx, offset);
                         let lllen = tr_base.len(bcx.ccx);
                         let llindex = bcx.sub(lllen, lloffset);
-                        (project_index(llindex), ptr::null_mut())
+                        ((tr_base.project_index(bcx, llindex), align), ptr::null_mut())
                     }
                     mir::ProjectionElem::Subslice { from, to } => {
-                        let llindex = C_uint(bcx.ccx, from);
-                        let (llbase, align) = project_index(llindex);
+                        let llbase = tr_base.project_index(bcx, C_uint(bcx.ccx, from));
 
                         let base_ty = tr_base.ty.to_ty(bcx.tcx());
                         match base_ty.sty {
index 3f29545ecf45a16c2bf8c59607503ce69a903322..da24c03fdc2a01bebb03ba1f35b10afe7ca23c23 100644 (file)
@@ -9,9 +9,10 @@
 // except according to those terms.
 
 use llvm::ValueRef;
-use rustc::ty::Ty;
+use rustc::ty::{self, Ty};
 use rustc::ty::layout::Layout;
 use rustc::mir;
+use rustc::mir::tcx::LvalueTy;
 use rustc_data_structures::indexed_vec::Idx;
 
 use base;
 use type_::Type;
 
 use std::fmt;
+use std::ptr;
 
 use super::{MirContext, LocalRef};
-use super::lvalue::Alignment;
+use super::lvalue::{Alignment, LvalueRef};
 
 /// The representation of a Rust value. The enum variant is in fact
 /// uniquely determined by the value's type, but is kept as a
@@ -86,6 +88,22 @@ pub fn immediate(self) -> ValueRef {
         }
     }
 
+    pub fn deref(self) -> LvalueRef<'tcx> {
+        let projected_ty = self.ty.builtin_deref(true, ty::NoPreference)
+            .unwrap().ty;
+        let (llptr, llextra) = match self.val {
+            OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()),
+            OperandValue::Pair(llptr, llextra) => (llptr, llextra),
+            OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self)
+        };
+        LvalueRef {
+            llval: llptr,
+            llextra: llextra,
+            ty: LvalueTy::from_ty(projected_ty),
+            alignment: Alignment::AbiAligned,
+        }
+    }
+
     /// If this operand is a Pair, we return an
     /// Immediate aggregate with the two values.
     pub fn pack_if_pair(mut self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
@@ -236,7 +254,7 @@ pub fn trans_operand(&mut self,
             }
 
             mir::Operand::Constant(ref constant) => {
-                let val = self.trans_constant(bcx, constant);
+                let val = self.trans_constant(&bcx, constant);
                 let operand = val.to_operand(bcx.ccx);
                 if let OperandValue::Ref(ptr, align) = operand.val {
                     // If this is a OperandValue::Ref to an immediate constant, load it.
index b6af4e52e820b9062fe1641fdcb1ea4aa5220f3e..d487aa6cd5be6f7d5e00dab89cc4683b80b2df9b 100644 (file)
 use rustc::ty::{self, Ty};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::layout::Layout;
-use rustc::ty::subst::{Kind, Subst};
 use rustc::mir::tcx::LvalueTy;
 use rustc::mir;
 use middle::lang_items::ExchangeMallocFnLangItem;
 
 use base;
 use builder::Builder;
-use callee::Callee;
+use callee;
 use common::{self, val_ty, C_bool, C_null, C_uint};
 use common::{C_integral};
 use adt;
 use machine;
+use monomorphize;
 use type_::Type;
 use type_of;
 use tvec;
@@ -98,8 +98,9 @@ pub fn trans_rvalue(&mut self,
                 let size = count.as_u64(bcx.tcx().sess.target.uint_type);
                 let size = C_uint(bcx.ccx, size);
                 let base = base::get_dataptr(&bcx, dest.llval);
-                tvec::slice_for_each(&bcx, base, tr_elem.ty, size, |bcx, llslot| {
+                tvec::slice_for_each(&bcx, base, tr_elem.ty, size, |bcx, llslot, loop_bb| {
                     self.store_operand(bcx, llslot, dest.alignment.to_align(), tr_elem);
+                    bcx.br(loop_bb);
                 })
             }
 
@@ -183,8 +184,7 @@ pub fn trans_rvalue_operand(&mut self,
                         match operand.ty.sty {
                             ty::TyFnDef(def_id, substs, _) => {
                                 OperandValue::Immediate(
-                                    Callee::def(bcx.ccx, def_id, substs)
-                                        .reify(bcx.ccx))
+                                    callee::resolve_and_get_fn(bcx.ccx, def_id, substs))
                             }
                             _ => {
                                 bug!("{} cannot be reified to a fn ptr", operand.ty)
@@ -194,20 +194,9 @@ pub fn trans_rvalue_operand(&mut self,
                     mir::CastKind::ClosureFnPointer => {
                         match operand.ty.sty {
                             ty::TyClosure(def_id, substs) => {
-                                // Get the def_id for FnOnce::call_once
-                                let fn_once = bcx.tcx().lang_items.fn_once_trait().unwrap();
-                                let call_once = bcx.tcx()
-                                    .global_tcx().associated_items(fn_once)
-                                    .find(|it| it.kind == ty::AssociatedKind::Method)
-                                    .unwrap().def_id;
-                                // Now create its substs [Closure, Tuple]
-                                let input = bcx.tcx().closure_type(def_id)
-                                    .subst(bcx.tcx(), substs.substs).input(0);
-                                let substs = bcx.tcx().mk_substs([operand.ty, input.skip_binder()]
-                                    .iter().cloned().map(Kind::from));
-                                OperandValue::Immediate(
-                                    Callee::def(bcx.ccx, call_once, substs)
-                                        .reify(bcx.ccx))
+                                let instance = monomorphize::resolve_closure(
+                                    bcx.ccx.shared(), def_id, substs, ty::ClosureKind::FnOnce);
+                                OperandValue::Immediate(callee::get_fn(bcx.ccx, instance))
                             }
                             _ => {
                                 bug!("{} cannot be cast to a fn ptr", operand.ty)
@@ -461,8 +450,8 @@ pub fn trans_rvalue_operand(&mut self,
                         bcx.sess().fatal(&format!("allocation of `{}` {}", box_ty, s));
                     }
                 };
-                let r = Callee::def(bcx.ccx, def_id, bcx.tcx().intern_substs(&[]))
-                    .reify(bcx.ccx);
+                let instance = ty::Instance::mono(bcx.tcx(), def_id);
+                let r = callee::get_fn(bcx.ccx, instance);
                 let val = bcx.pointercast(bcx.call(r, &[llsize, llalign], None), llty_ptr);
 
                 let operand = OperandRef {
@@ -471,7 +460,6 @@ pub fn trans_rvalue_operand(&mut self,
                 };
                 (bcx, operand)
             }
-
             mir::Rvalue::Use(ref operand) => {
                 let operand = self.trans_operand(&bcx, operand);
                 (bcx, operand)
@@ -674,7 +662,7 @@ pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool {
         mir::Rvalue::UnaryOp(..) |
         mir::Rvalue::Discriminant(..) |
         mir::Rvalue::Box(..) |
-        mir::Rvalue::Use(..) =>
+        mir::Rvalue::Use(..) => // (*)
             true,
         mir::Rvalue::Repeat(..) |
         mir::Rvalue::Aggregate(..) =>
index 4b31d5b7f88de1ac9258351683a9c222e41e8c72..fcf6937d4b6d58670681f042e9bc6deedc71076b 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use abi::Abi;
 use common::*;
+use glue;
+
 use rustc::hir::def_id::DefId;
 use rustc::infer::TransNormalize;
-use rustc::traits;
+use rustc::middle::lang_items::DropInPlaceFnLangItem;
+use rustc::traits::{self, SelectionContext, Reveal};
+use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::ty::fold::{TypeFolder, TypeFoldable};
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::util::ppaux;
 use rustc::util::common::MemoizationMap;
 
-use syntax::codemap::DUMMY_SP;
+use syntax::ast;
+use syntax::codemap::{Span, DUMMY_SP};
+
+pub use rustc::ty::Instance;
+
+fn fn_once_adapter_instance<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    closure_did: DefId,
+    substs: ty::ClosureSubsts<'tcx>,
+    ) -> Instance<'tcx> {
+    debug!("fn_once_adapter_shim({:?}, {:?})",
+           closure_did,
+           substs);
+    let fn_once = tcx.lang_items.fn_once_trait().unwrap();
+    let call_once = tcx.associated_items(fn_once)
+        .find(|it| it.kind == ty::AssociatedKind::Method)
+        .unwrap().def_id;
+    let def = ty::InstanceDef::ClosureOnceShim { call_once };
 
-use std::fmt;
+    let self_ty = tcx.mk_closure_from_closure_substs(
+        closure_did, substs);
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub struct Instance<'tcx> {
-    pub def: DefId,
-    pub substs: &'tcx Substs<'tcx>,
+    let sig = tcx.closure_type(closure_did).subst(tcx, substs.substs);
+    let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
+    assert_eq!(sig.inputs().len(), 1);
+    let substs = tcx.mk_substs([
+        Kind::from(self_ty),
+        Kind::from(sig.inputs()[0]),
+    ].iter().cloned());
+
+    debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
+    Instance { def, substs }
 }
 
-impl<'tcx> fmt::Display for Instance<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        ppaux::parameterized(f, &self.substs, self.def, &[])
+fn needs_fn_once_adapter_shim(actual_closure_kind: ty::ClosureKind,
+                              trait_closure_kind: ty::ClosureKind)
+                              -> Result<bool, ()>
+{
+    match (actual_closure_kind, trait_closure_kind) {
+        (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
+        (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
+        (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
+            // No adapter needed.
+           Ok(false)
+        }
+        (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
+            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
+            // `fn(&mut self, ...)`. In fact, at trans time, these are
+            // basically the same thing, so we can just return llfn.
+            Ok(false)
+        }
+        (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
+        (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
+            // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
+            // self, ...)`.  We want a `fn(self, ...)`. We can produce
+            // this by doing something like:
+            //
+            //     fn call_once(self, ...) { call_mut(&self, ...) }
+            //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
+            //
+            // These are both the same at trans time.
+            Ok(true)
+        }
+        _ => Err(()),
     }
 }
 
-impl<'a, 'tcx> Instance<'tcx> {
-    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
-               -> Instance<'tcx> {
-        assert!(substs.regions().all(|&r| r == ty::ReErased));
-        Instance { def: def_id, substs: substs }
-    }
+pub fn resolve_closure<'a, 'tcx> (
+    scx: &SharedCrateContext<'a, 'tcx>,
+    def_id: DefId,
+    substs: ty::ClosureSubsts<'tcx>,
+    requested_kind: ty::ClosureKind)
+    -> Instance<'tcx>
+{
+    let actual_kind = scx.tcx().closure_kind(def_id);
 
-    pub fn mono(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> {
-        Instance::new(def_id, scx.empty_substs_for_def_id(def_id))
+    match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
+        Ok(true) => fn_once_adapter_instance(scx.tcx(), def_id, substs),
+        _ => Instance::new(def_id, substs.substs)
     }
+}
 
-    /// For associated constants from traits, return the impl definition.
-    pub fn resolve_const(&self, scx: &SharedCrateContext<'a, 'tcx>) -> Self {
-        if let Some(trait_id) = scx.tcx().trait_of_item(self.def) {
-            let trait_ref = ty::TraitRef::new(trait_id, self.substs);
-            let trait_ref = ty::Binder(trait_ref);
-            let vtable = fulfill_obligation(scx, DUMMY_SP, trait_ref);
-            if let traits::VtableImpl(vtable_impl) = vtable {
-                let name = scx.tcx().item_name(self.def);
-                let ac = scx.tcx().associated_items(vtable_impl.impl_def_id)
-                    .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name);
-                if let Some(ac) = ac {
-                    return Instance::new(ac.def_id, vtable_impl.substs);
+/// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
+/// do not (necessarily) resolve all nested obligations on the impl. Note that type check should
+/// guarantee to us that all nested obligations *could be* resolved if we wanted to.
+fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
+                                span: Span,
+                                trait_ref: ty::PolyTraitRef<'tcx>)
+                                -> traits::Vtable<'tcx, ()>
+{
+    let tcx = scx.tcx();
+
+    // Remove any references to regions; this helps improve caching.
+    let trait_ref = tcx.erase_regions(&trait_ref);
+
+    scx.trait_cache().memoize(trait_ref, || {
+        debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
+               trait_ref, trait_ref.def_id());
+
+        // Do the initial selection for the obligation. This yields the
+        // shallow result we are looking for -- that is, what specific impl.
+        tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
+            let mut selcx = SelectionContext::new(&infcx);
+
+            let obligation_cause = traits::ObligationCause::misc(span,
+                                                             ast::DUMMY_NODE_ID);
+            let obligation = traits::Obligation::new(obligation_cause,
+                                                     trait_ref.to_poly_trait_predicate());
+
+            let selection = match selcx.select(&obligation) {
+                Ok(Some(selection)) => selection,
+                Ok(None) => {
+                    // Ambiguity can happen when monomorphizing during trans
+                    // expands to some humongo type that never occurred
+                    // statically -- this humongo type can then overflow,
+                    // leading to an ambiguous result. So report this as an
+                    // overflow bug, since I believe this is the only case
+                    // where ambiguity can result.
+                    debug!("Encountered ambiguity selecting `{:?}` during trans, \
+                            presuming due to overflow",
+                           trait_ref);
+                    tcx.sess.span_fatal(span,
+                        "reached the recursion limit during monomorphization \
+                         (selection ambiguity)");
                 }
+                Err(e) => {
+                    span_bug!(span, "Encountered error `{:?}` selecting `{:?}` during trans",
+                              e, trait_ref)
+                }
+            };
+
+            debug!("fulfill_obligation: selection={:?}", selection);
+
+            // Currently, we use a fulfillment context to completely resolve
+            // all nested obligations. This is because they can inform the
+            // inference of the impl's type parameters.
+            let mut fulfill_cx = traits::FulfillmentContext::new();
+            let vtable = selection.map(|predicate| {
+                debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
+                fulfill_cx.register_predicate_obligation(&infcx, predicate);
+            });
+            let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable);
+
+            info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
+            vtable
+        })
+    })
+}
+
+fn resolve_associated_item<'a, 'tcx>(
+    scx: &SharedCrateContext<'a, 'tcx>,
+    trait_item: &ty::AssociatedItem,
+    trait_id: DefId,
+    rcvr_substs: &'tcx Substs<'tcx>
+) -> Instance<'tcx> {
+    let tcx = scx.tcx();
+    let def_id = trait_item.def_id;
+    debug!("resolve_associated_item(trait_item={:?}, \
+                                    trait_id={:?}, \
+                                    rcvr_substs={:?})",
+           def_id, trait_id, rcvr_substs);
+
+    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
+    let vtbl = fulfill_obligation(scx, DUMMY_SP, ty::Binder(trait_ref));
+
+    // Now that we know which impl is being used, we can dispatch to
+    // the actual function:
+    match vtbl {
+        traits::VtableImpl(impl_data) => {
+            let (def_id, substs) = traits::find_associated_item(
+                tcx, trait_item, rcvr_substs, &impl_data);
+            let substs = tcx.erase_regions(&substs);
+            ty::Instance::new(def_id, substs)
+        }
+        traits::VtableClosure(closure_data) => {
+            let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
+            resolve_closure(scx, closure_data.closure_def_id, closure_data.substs,
+                            trait_closure_kind)
+        }
+        traits::VtableFnPointer(ref data) => {
+            Instance {
+                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
+                substs: rcvr_substs
             }
         }
+        traits::VtableObject(ref data) => {
+            let index = tcx.get_vtable_index_of_object_method(data, def_id);
+            Instance {
+                def: ty::InstanceDef::Virtual(def_id, index),
+                substs: rcvr_substs
+            }
+        }
+        _ => {
+            bug!("static call to invalid vtable: {:?}", vtbl)
+        }
+    }
+}
 
-        *self
+/// The point where linking happens. Resolve a (def_id, substs)
+/// pair to an instance.
+pub fn resolve<'a, 'tcx>(
+    scx: &SharedCrateContext<'a, 'tcx>,
+    def_id: DefId,
+    substs: &'tcx Substs<'tcx>
+) -> Instance<'tcx> {
+    debug!("resolve(def_id={:?}, substs={:?})",
+           def_id, substs);
+    let result = if let Some(trait_def_id) = scx.tcx().trait_of_item(def_id) {
+        debug!(" => associated item, attempting to find impl");
+        let item = scx.tcx().associated_item(def_id);
+        resolve_associated_item(scx, &item, trait_def_id, substs)
+    } else {
+        let item_type = def_ty(scx, def_id, substs);
+        let def = match item_type.sty {
+            ty::TyFnDef(_, _, f) if
+                f.abi() == Abi::RustIntrinsic ||
+                f.abi() == Abi::PlatformIntrinsic =>
+            {
+                debug!(" => intrinsic");
+                ty::InstanceDef::Intrinsic(def_id)
+            }
+            _ => {
+                if Some(def_id) == scx.tcx().lang_items.drop_in_place_fn() {
+                    let ty = substs.type_at(0);
+                    if glue::needs_drop_glue(scx, ty) {
+                        debug!(" => nontrivial drop glue");
+                        ty::InstanceDef::DropGlue(def_id, Some(ty))
+                    } else {
+                        debug!(" => trivial drop glue");
+                        ty::InstanceDef::DropGlue(def_id, None)
+                    }
+                } else {
+                    debug!(" => free item");
+                    ty::InstanceDef::Item(def_id)
+                }
+            }
+        };
+        Instance { def, substs }
+    };
+    debug!("resolve(def_id={:?}, substs={:?}) = {}",
+           def_id, substs, result);
+    result
+}
+
+pub fn resolve_drop_in_place<'a, 'tcx>(
+    scx: &SharedCrateContext<'a, 'tcx>,
+    ty: Ty<'tcx>)
+    -> ty::Instance<'tcx>
+{
+    let def_id = scx.tcx().require_lang_item(DropInPlaceFnLangItem);
+    let substs = scx.tcx().intern_substs(&[Kind::from(ty)]);
+    resolve(scx, def_id, substs)
+}
+
+pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx>,
+                                             source_ty: Ty<'tcx>,
+                                             target_ty: Ty<'tcx>)
+                                             -> CustomCoerceUnsized {
+    let trait_ref = ty::Binder(ty::TraitRef {
+        def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(),
+        substs: scx.tcx().mk_substs_trait(source_ty, &[target_ty])
+    });
+
+    match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
+        traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
+            scx.tcx().custom_coerce_unsized_kind(impl_def_id)
+        }
+        vtable => {
+            bug!("invalid CoerceUnsized vtable: {:?}", vtable);
+        }
     }
 }
 
@@ -80,7 +310,6 @@ pub fn apply_param_substs<'a, 'tcx, T>(scx: &SharedCrateContext<'a, 'tcx>,
     AssociatedTypeNormalizer::new(scx).fold(&substituted)
 }
 
-
 /// Returns the normalized type of a struct field
 pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           param_substs: &Substs<'tcx>,
index cc9fd8f46f6f0236c7e927d29ea6a04bef86084e..90ce40cfbcf8fa3f27f3f33cbeb781baca05ab39 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
 use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
-use rustc::ty::TyCtxt;
+use rustc::ty::{self, TyCtxt};
 use rustc::ty::item_path::characteristic_def_id_of_type;
 use rustc_incremental::IchHasher;
 use std::cmp::Ordering;
@@ -186,14 +186,14 @@ pub fn compute_symbol_name_hash(&self,
             symbol_name.hash(&mut state);
             let exported = match item {
                TransItem::Fn(ref instance) => {
-                    let node_id = scx.tcx().hir.as_local_node_id(instance.def);
+                   let node_id =
+                       scx.tcx().hir.as_local_node_id(instance.def_id());
                     node_id.map(|node_id| exported_symbols.contains(&node_id))
                            .unwrap_or(false)
                }
                TransItem::Static(node_id) => {
                     exported_symbols.contains(&node_id)
                }
-               TransItem::DropGlue(..) => false,
             };
             exported.hash(&mut state);
         }
@@ -241,10 +241,9 @@ pub fn items_in_deterministic_order(&self,
         fn local_node_id(tcx: TyCtxt, trans_item: TransItem) -> Option<NodeId> {
             match trans_item {
                 TransItem::Fn(instance) => {
-                    tcx.hir.as_local_node_id(instance.def)
+                    tcx.hir.as_local_node_id(instance.def_id())
                 }
                 TransItem::Static(node_id) => Some(node_id),
-                TransItem::DropGlue(_) => None,
             }
         }
     }
@@ -340,7 +339,6 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
                     match trans_item {
                         TransItem::Fn(..) |
                         TransItem::Static(..) => llvm::ExternalLinkage,
-                        TransItem::DropGlue(..) => unreachable!(),
                     }
                 }
             };
@@ -455,17 +453,26 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 't
     let tcx = scx.tcx();
     match trans_item {
         TransItem::Fn(instance) => {
+            let def_id = match instance.def {
+                ty::InstanceDef::Item(def_id) => def_id,
+                ty::InstanceDef::FnPtrShim(..) |
+                ty::InstanceDef::ClosureOnceShim { .. } |
+                ty::InstanceDef::Intrinsic(..) |
+                ty::InstanceDef::DropGlue(..) |
+                ty::InstanceDef::Virtual(..) => return None
+            };
+
             // If this is a method, we want to put it into the same module as
             // its self-type. If the self-type does not provide a characteristic
             // DefId, we use the location of the impl after all.
 
-            if tcx.trait_of_item(instance.def).is_some() {
+            if tcx.trait_of_item(def_id).is_some() {
                 let self_ty = instance.substs.type_at(0);
                 // This is an implementation of a trait method.
-                return characteristic_def_id_of_type(self_ty).or(Some(instance.def));
+                return characteristic_def_id_of_type(self_ty).or(Some(def_id));
             }
 
-            if let Some(impl_def_id) = tcx.impl_of_method(instance.def) {
+            if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
                 // This is a method within an inherent impl, find out what the
                 // self-type is:
                 let impl_self_ty = common::def_ty(scx, impl_def_id, instance.substs);
@@ -474,9 +481,8 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 't
                 }
             }
 
-            Some(instance.def)
+            Some(def_id)
         }
-        TransItem::DropGlue(dg) => characteristic_def_id_of_type(dg.ty()),
         TransItem::Static(node_id) => Some(tcx.hir.local_def_id(node_id)),
     }
 }
index 880c65937e3087f826a8bd079c4d57a0e7ef1a22..1b48e131b720a2c5e5a3b01c5e7597cbd524c235 100644 (file)
@@ -97,10 +97,9 @@ fn get_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               trans_item: TransItem<'tcx>) -> Option<Span> {
             match trans_item {
                 TransItem::Fn(Instance { def, .. }) => {
-                    tcx.hir.as_local_node_id(def)
+                    tcx.hir.as_local_node_id(def.def_id())
                 }
                 TransItem::Static(node_id) => Some(node_id),
-                TransItem::DropGlue(_) => None,
             }.map(|node_id| {
                 tcx.hir.span(node_id)
             })
index 02e1290b5778331d0e5734100811561d78196448..fe551b06b3d95cff1b7e774139d7fbd99f5a19d9 100644 (file)
@@ -14,6 +14,7 @@
 //! item-path. This is used for unit testing the code that generates
 //! paths etc in all kinds of annoying scenarios.
 
+use back::symbol_names;
 use rustc::hir;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use syntax::ast;
@@ -51,8 +52,8 @@ fn process_attrs(&mut self,
         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(self.scx, def_id);
-                let name = instance.symbol_name(self.scx);
+                let instance = Instance::mono(tcx, def_id);
+                let name = symbol_names::symbol_name(instance, self.scx);
                 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);
@@ -86,4 +87,3 @@ fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
         intravisit::walk_impl_item(self, ii)
     }
 }
-
index d19f04b9554fb287580e33aeb602c66b2e5906ee..410e3f30be731eb0622e0a659030f04215094612 100644 (file)
@@ -20,7 +20,6 @@
 use context::{CrateContext, SharedCrateContext};
 use common;
 use declare;
-use glue::DropGlueKind;
 use llvm;
 use monomorphize::Instance;
 use rustc::dep_graph::DepNode;
 use syntax::ast::{self, NodeId};
 use syntax::attr;
 use type_of;
-use glue;
-use abi::{Abi, FnType};
 use back::symbol_names;
 use std::fmt::Write;
 use std::iter;
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub enum TransItem<'tcx> {
-    DropGlue(DropGlueKind<'tcx>),
     Fn(Instance<'tcx>),
     Static(NodeId)
 }
@@ -95,13 +91,10 @@ pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
             }
             TransItem::Fn(instance) => {
                 let _task = ccx.tcx().dep_graph.in_task(
-                    DepNode::TransCrateItem(instance.def)); // (*)
+                    DepNode::TransCrateItem(instance.def_id())); // (*)
 
                 base::trans_instance(&ccx, instance);
             }
-            TransItem::DropGlue(dg) => {
-                glue::implement_drop_glue(&ccx, dg);
-            }
         }
 
         debug!("END IMPLEMENTING '{} ({})' in cgu {}",
@@ -130,9 +123,6 @@ pub fn predefine(&self,
             TransItem::Fn(instance) => {
                 TransItem::predefine_fn(ccx, instance, linkage, &symbol_name);
             }
-            TransItem::DropGlue(dg) => {
-                TransItem::predefine_drop_glue(ccx, dg, linkage, &symbol_name);
-            }
         }
 
         debug!("END PREDEFINING '{} ({})' in cgu {}",
@@ -146,7 +136,8 @@ fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
                         linkage: llvm::Linkage,
                         symbol_name: &str) {
         let def_id = ccx.tcx().hir.local_def_id(node_id);
-        let ty = common::def_ty(ccx.shared(), def_id, Substs::empty());
+        let instance = Instance::mono(ccx.tcx(), def_id);
+        let ty = common::instance_ty(ccx.shared(), &instance);
         let llty = type_of::type_of(ccx, ty);
 
         let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
@@ -156,7 +147,6 @@ fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
 
         unsafe { llvm::LLVMRustSetLinkage(g, linkage) };
 
-        let instance = Instance::mono(ccx.shared(), def_id);
         ccx.instances().borrow_mut().insert(instance, g);
         ccx.statics().borrow_mut().insert(g, def_id);
     }
@@ -168,8 +158,8 @@ fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
         assert!(!instance.substs.needs_infer() &&
                 !instance.substs.has_param_types());
 
-        let mono_ty = common::def_ty(ccx.shared(), instance.def, instance.substs);
-        let attrs = ccx.tcx().get_attrs(instance.def);
+        let mono_ty = common::instance_ty(ccx.shared(), &instance);
+        let attrs = instance.def.attrs(ccx.tcx());
         let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
         unsafe { llvm::LLVMRustSetLinkage(lldecl, linkage) };
         base::set_link_section(ccx, lldecl, &attrs);
@@ -178,88 +168,39 @@ fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
             llvm::SetUniqueComdat(ccx.llmod(), lldecl);
         }
 
-        if let ty::TyClosure(..) = mono_ty.sty {
-            // set an inline hint for all closures
+        debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance);
+        if common::is_inline_instance(ccx.tcx(), &instance) {
             attributes::inline(lldecl, attributes::InlineAttr::Hint);
         }
-
         attributes::from_fn_attrs(ccx, &attrs, lldecl);
 
         ccx.instances().borrow_mut().insert(instance, lldecl);
     }
 
-    fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
-                           dg: glue::DropGlueKind<'tcx>,
-                           linkage: llvm::Linkage,
-                           symbol_name: &str) {
-        let tcx = ccx.tcx();
-        assert_eq!(dg.ty(), glue::get_drop_glue_type(ccx.shared(), dg.ty()));
-        let t = dg.ty();
-
-        let sig = tcx.mk_fn_sig(
-            iter::once(tcx.mk_mut_ptr(t)),
-            tcx.mk_nil(),
-            false,
-            hir::Unsafety::Normal,
-            Abi::Rust
-        );
-
-        debug!("predefine_drop_glue: sig={}", sig);
-
-        let fn_ty = FnType::new(ccx, sig, &[]);
-        let llfnty = fn_ty.llvm_type(ccx);
-
-        assert!(declare::get_defined_value(ccx, symbol_name).is_none());
-        let llfn = declare::declare_cfn(ccx, symbol_name, llfnty);
-        unsafe { llvm::LLVMRustSetLinkage(llfn, linkage) };
-        if linkage == llvm::Linkage::LinkOnceODRLinkage ||
-           linkage == llvm::Linkage::WeakODRLinkage {
-            llvm::SetUniqueComdat(ccx.llmod(), llfn);
-        }
-        attributes::set_frame_pointer_elimination(ccx, llfn);
-        ccx.drop_glues().borrow_mut().insert(dg, (llfn, fn_ty));
-    }
-
     pub fn compute_symbol_name(&self,
                                scx: &SharedCrateContext<'a, 'tcx>) -> String {
         match *self {
-            TransItem::Fn(instance) => instance.symbol_name(scx),
+            TransItem::Fn(instance) => symbol_names::symbol_name(instance, scx),
             TransItem::Static(node_id) => {
                 let def_id = scx.tcx().hir.local_def_id(node_id);
-                Instance::mono(scx, def_id).symbol_name(scx)
-            }
-            TransItem::DropGlue(dg) => {
-                let prefix = match dg {
-                    DropGlueKind::Ty(_) => "drop",
-                    DropGlueKind::TyContents(_) => "drop_contents",
-                };
-                symbol_names::exported_name_from_type_and_prefix(scx, dg.ty(), prefix)
+                symbol_names::symbol_name(Instance::mono(scx.tcx(), def_id), scx)
             }
         }
     }
 
-    pub fn is_from_extern_crate(&self) -> bool {
-        match *self {
-            TransItem::Fn(ref instance) => !instance.def.is_local(),
-            TransItem::DropGlue(..) |
-            TransItem::Static(..)   => false,
-        }
-    }
-
     pub fn instantiation_mode(&self,
                               tcx: TyCtxt<'a, 'tcx, 'tcx>)
                               -> InstantiationMode {
         match *self {
             TransItem::Fn(ref instance) => {
                 if self.explicit_linkage(tcx).is_none() &&
-                   (common::is_closure(tcx, instance.def) ||
-                    attr::requests_inline(&tcx.get_attrs(instance.def)[..])) {
+                    common::requests_inline(tcx, instance)
+                {
                     InstantiationMode::LocalCopy
                 } else {
                     InstantiationMode::GloballyShared
                 }
             }
-            TransItem::DropGlue(..) => InstantiationMode::LocalCopy,
             TransItem::Static(..) => InstantiationMode::GloballyShared,
         }
     }
@@ -269,16 +210,14 @@ pub fn is_generic_fn(&self) -> bool {
             TransItem::Fn(ref instance) => {
                 instance.substs.types().next().is_some()
             }
-            TransItem::DropGlue(..) |
             TransItem::Static(..)   => false,
         }
     }
 
     pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
         let def_id = match *self {
-            TransItem::Fn(ref instance) => instance.def,
+            TransItem::Fn(ref instance) => instance.def_id(),
             TransItem::Static(node_id) => tcx.hir.local_def_id(node_id),
-            TransItem::DropGlue(..) => return None,
         };
 
         let attributes = tcx.get_attrs(def_id);
@@ -302,16 +241,6 @@ pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
         let hir_map = &tcx.hir;
 
         return match *self {
-            TransItem::DropGlue(dg) => {
-                let mut s = String::with_capacity(32);
-                match dg {
-                    DropGlueKind::Ty(_) => s.push_str("drop-glue "),
-                    DropGlueKind::TyContents(_) => s.push_str("drop-glue-contents "),
-                };
-                let printer = DefPathBasedNames::new(tcx, false, false);
-                printer.push_type_name(dg.ty(), &mut s);
-                s
-            }
             TransItem::Fn(instance) => {
                 to_string_internal(tcx, "fn ", instance)
             },
@@ -336,13 +265,6 @@ fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     pub fn to_raw_string(&self) -> String {
         match *self {
-            TransItem::DropGlue(dg) => {
-                let prefix = match dg {
-                    DropGlueKind::Ty(_) => "Ty",
-                    DropGlueKind::TyContents(_) => "TyContents",
-                };
-                format!("DropGlue({}: {})", prefix, dg.ty() as *const _ as usize)
-            }
             TransItem::Fn(instance) => {
                 format!("Fn({:?}, {})",
                          instance.def,
@@ -581,7 +503,7 @@ fn push_type_params<I>(&self,
     pub fn push_instance_as_string(&self,
                                    instance: Instance<'tcx>,
                                    output: &mut String) {
-        self.push_def_path(instance.def, output);
+        self.push_def_path(instance.def_id(), output);
         self.push_type_params(instance.substs, iter::empty(), output);
     }
 }
index cbcbb02bdc89017ebb573ad6a9c06b57f2d94620..4216a73a8dd85b1ea2deae5865ec160a2235c279 100644 (file)
@@ -10,7 +10,7 @@
 
 use llvm;
 use builder::Builder;
-use llvm::ValueRef;
+use llvm::{BasicBlockRef, ValueRef};
 use common::*;
 use rustc::ty::Ty;
 
@@ -20,7 +20,7 @@ pub fn slice_for_each<'a, 'tcx, F>(
     unit_ty: Ty<'tcx>,
     len: ValueRef,
     f: F
-) -> Builder<'a, 'tcx> where F: FnOnce(&Builder<'a, 'tcx>, ValueRef) {
+) -> Builder<'a, 'tcx> where F: FnOnce(&Builder<'a, 'tcx>, ValueRef, BasicBlockRef) {
     // Special-case vectors with elements of size 0  so they don't go out of bounds (#9890)
     let zst = type_is_zero_size(bcx.ccx, unit_ty);
     let add = |bcx: &Builder, a, b| if zst {
@@ -46,9 +46,8 @@ pub fn slice_for_each<'a, 'tcx, F>(
     let keep_going = header_bcx.icmp(llvm::IntNE, current, end);
     header_bcx.cond_br(keep_going, body_bcx.llbb(), next_bcx.llbb());
 
-    f(&body_bcx, if zst { data_ptr } else { current });
     let next = add(&body_bcx, current, C_uint(bcx.ccx, 1usize));
+    f(&body_bcx, if zst { data_ptr } else { current }, header_bcx.llbb());
     header_bcx.add_incoming_to_phi(current, next, body_bcx.llbb());
-    body_bcx.br(header_bcx.llbb());
     next_bcx
 }
index 4b88f5acf42da2415ea3442fec3c06440ef307b2..529ee107c46cee8db04acf0ff6f9ba53801b757a 100644 (file)
@@ -254,7 +254,7 @@ fn confirm_builtin_call(&self,
 
         // Call the generic checker.
         let expected_arg_tys =
-            self.expected_types_for_fn_args(call_expr.span,
+            self.expected_inputs_for_expected_output(call_expr.span,
                                             expected,
                                             fn_sig.output(),
                                             fn_sig.inputs());
@@ -280,7 +280,7 @@ fn confirm_deferred_closure_call(&self,
         // do know the types expected for each argument and the return
         // type.
 
-        let expected_arg_tys = self.expected_types_for_fn_args(call_expr.span,
+        let expected_arg_tys = self.expected_inputs_for_expected_output(call_expr.span,
                                                                expected,
                                                                fn_sig.output().clone(),
                                                                fn_sig.inputs());
index 28996b40cfdfec0f2fa7d76df348e78311f00525..2861fd288326b001f639e03bbf4fd7bb7f61a140 100644 (file)
@@ -273,6 +273,8 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             "unchecked_div" | "unchecked_rem" =>
                 (1, vec![param(0), param(0)], param(0)),
+            "unchecked_shl" | "unchecked_shr" =>
+                (1, vec![param(0), param(0)], param(0)),
 
             "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
                 (1, vec![param(0), param(0)], param(0)),
index 5a582a523ea1c910a6c52102b4104b2ec352ccfc..c857388106d5ad6c2fe89e628c3f3b657b158e3e 100644 (file)
@@ -402,7 +402,7 @@ fn always(self) -> bool {
 }
 
 #[derive(Clone)]
-pub struct LoopCtxt<'gcx, 'tcx> {
+pub struct BreakableCtxt<'gcx, 'tcx> {
     unified: Ty<'tcx>,
     coerce_to: Ty<'tcx>,
     break_exprs: Vec<&'gcx hir::Expr>,
@@ -410,15 +410,17 @@ pub struct LoopCtxt<'gcx, 'tcx> {
 }
 
 #[derive(Clone)]
-pub struct EnclosingLoops<'gcx, 'tcx> {
-    stack: Vec<LoopCtxt<'gcx, 'tcx>>,
+pub struct EnclosingBreakables<'gcx, 'tcx> {
+    stack: Vec<BreakableCtxt<'gcx, 'tcx>>,
     by_id: NodeMap<usize>,
 }
 
-impl<'gcx, 'tcx> EnclosingLoops<'gcx, 'tcx> {
-    fn find_loop(&mut self, id: hir::LoopIdResult) -> Option<&mut LoopCtxt<'gcx, 'tcx>> {
-        let id_res: Result<_,_> = id.into();
-        if let Some(ix) = id_res.ok().and_then(|id| self.by_id.get(&id).cloned()) {
+impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> {
+    fn find_breakable(&mut self, target: hir::ScopeTarget)
+        -> Option<&mut BreakableCtxt<'gcx, 'tcx>>
+    {
+        let opt_index = target.opt_id().and_then(|id| self.by_id.get(&id).cloned());
+        if let Some(ix) = opt_index {
             Some(&mut self.stack[ix])
         } else {
             None
@@ -448,7 +450,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// Whether any child nodes have any type errors.
     has_errors: Cell<bool>,
 
-    enclosing_loops: RefCell<EnclosingLoops<'gcx, 'tcx>>,
+    enclosing_breakables: RefCell<EnclosingBreakables<'gcx, 'tcx>>,
 
     inh: &'a Inherited<'a, 'gcx, 'tcx>,
 }
@@ -1429,7 +1431,7 @@ pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
                                                      ast::CRATE_NODE_ID)),
             diverges: Cell::new(Diverges::Maybe),
             has_errors: Cell::new(false),
-            enclosing_loops: RefCell::new(EnclosingLoops {
+            enclosing_breakables: RefCell::new(EnclosingBreakables {
                 stack: Vec::new(),
                 by_id: NodeMap(),
             }),
@@ -2292,7 +2294,7 @@ fn check_method_argument_types(&self,
             match method_fn_ty.sty {
                 ty::TyFnDef(def_id, .., ref fty) => {
                     // HACK(eddyb) ignore self in the definition (see above).
-                    let expected_arg_tys = self.expected_types_for_fn_args(
+                    let expected_arg_tys = self.expected_inputs_for_expected_output(
                         sp,
                         expected,
                         fty.0.output(),
@@ -2645,14 +2647,14 @@ pub fn impl_self_ty(&self,
         TypeAndSubsts { substs: substs, ty: substd_ty }
     }
 
-    /// Unifies the return type with the expected type early, for more coercions
-    /// and forward type information on the argument expressions.
-    fn expected_types_for_fn_args(&self,
-                                  call_span: Span,
-                                  expected_ret: Expectation<'tcx>,
-                                  formal_ret: Ty<'tcx>,
-                                  formal_args: &[Ty<'tcx>])
-                                  -> Vec<Ty<'tcx>> {
+    /// Unifies the output type with the expected type early, for more coercions
+    /// and forward type information on the input expressions.
+    fn expected_inputs_for_expected_output(&self,
+                                           call_span: Span,
+                                           expected_ret: Expectation<'tcx>,
+                                           formal_ret: Ty<'tcx>,
+                                           formal_args: &[Ty<'tcx>])
+                                           -> Vec<Ty<'tcx>> {
         let expected_args = expected_ret.only_has_type(self).and_then(|ret_ty| {
             self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || {
                 // Attempt to apply a subtyping relationship between the formal
@@ -2675,7 +2677,7 @@ fn expected_types_for_fn_args(&self,
                 }).collect())
             }).ok()
         }).unwrap_or(vec![]);
-        debug!("expected_types_for_fn_args(formal={:?} -> {:?}, expected={:?} -> {:?})",
+        debug!("expected_inputs_for_expected_output(formal={:?} -> {:?}, expected={:?} -> {:?})",
                formal_args, formal_ret,
                expected_args, expected_ret);
         expected_args
@@ -3032,14 +3034,22 @@ fn report_unknown_field(&self,
 
     fn check_expr_struct_fields(&self,
                                 adt_ty: Ty<'tcx>,
+                                expected: Expectation<'tcx>,
                                 expr_id: ast::NodeId,
                                 span: Span,
                                 variant: &'tcx ty::VariantDef,
                                 ast_fields: &'gcx [hir::Field],
                                 check_completeness: bool) {
         let tcx = self.tcx;
-        let (substs, adt_kind, kind_name) = match adt_ty.sty {
-            ty::TyAdt(adt, substs) => (substs, adt.adt_kind(), adt.variant_descr()),
+
+        let adt_ty_hint =
+            self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty])
+                .get(0).cloned().unwrap_or(adt_ty);
+
+        let (substs, hint_substs, adt_kind, kind_name) = match (&adt_ty.sty, &adt_ty_hint.sty) {
+            (&ty::TyAdt(adt, substs), &ty::TyAdt(_, hint_substs)) => {
+                (substs, hint_substs, adt.adt_kind(), adt.variant_descr())
+            }
             _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields")
         };
 
@@ -3054,10 +3064,12 @@ fn check_expr_struct_fields(&self,
 
         // Typecheck each field.
         for field in ast_fields {
-            let expected_field_type;
+            let final_field_type;
+            let field_type_hint;
 
             if let Some(v_field) = remaining_fields.remove(&field.name.node) {
-                expected_field_type = self.field_ty(field.span, v_field, substs);
+                final_field_type = self.field_ty(field.span, v_field, substs);
+                field_type_hint = self.field_ty(field.span, v_field, hint_substs);
 
                 seen_fields.insert(field.name.node, field.span);
 
@@ -3069,7 +3081,8 @@ fn check_expr_struct_fields(&self,
                 }
             } else {
                 error_happened = true;
-                expected_field_type = tcx.types.err;
+                final_field_type = tcx.types.err;
+                field_type_hint = tcx.types.err;
                 if let Some(_) = variant.find_field_named(field.name.node) {
                     let mut err = struct_span_err!(self.tcx.sess,
                                                 field.name.span,
@@ -3091,7 +3104,8 @@ fn check_expr_struct_fields(&self,
 
             // Make sure to give a type to the field even if there's
             // an error, so we can continue typechecking
-            self.check_expr_coercable_to_type(&field.expr, expected_field_type);
+            let ty = self.check_expr_with_hint(&field.expr, field_type_hint);
+            self.demand_coerce(&field.expr, ty, final_field_type);
         }
 
         // Make sure the programmer specified correct number of fields.
@@ -3201,6 +3215,7 @@ pub fn check_struct_path(&self,
 
     fn check_expr_struct(&self,
                          expr: &hir::Expr,
+                         expected: Expectation<'tcx>,
                          qpath: &hir::QPath,
                          fields: &'gcx [hir::Field],
                          base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx>
@@ -3219,7 +3234,7 @@ fn check_expr_struct(&self,
             hir::QPath::TypeRelative(ref qself, _) => qself.span
         };
 
-        self.check_expr_struct_fields(struct_ty, expr.id, path_span, variant, fields,
+        self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields,
                                       base_expr.is_none());
         if let &Some(ref base_expr) = base_expr {
             self.check_expr_has_type(base_expr, struct_ty);
@@ -3467,10 +3482,11 @@ fn check_expr_kind(&self,
               }
               tcx.mk_nil()
           }
-          hir::ExprBreak(label, ref expr_opt) => {
+          hir::ExprBreak(destination, ref expr_opt) => {
             let coerce_to = {
-                let mut enclosing_loops = self.enclosing_loops.borrow_mut();
-                enclosing_loops.find_loop(label.loop_id).map(|ctxt| ctxt.coerce_to)
+                let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
+                enclosing_breakables
+                    .find_breakable(destination.target_id).map(|ctxt| ctxt.coerce_to)
             };
             if let Some(coerce_to) = coerce_to {
                 let e_ty;
@@ -3486,8 +3502,8 @@ fn check_expr_kind(&self,
                     cause = self.misc(expr.span);
                 }
 
-                let mut enclosing_loops = self.enclosing_loops.borrow_mut();
-                let ctxt = enclosing_loops.find_loop(label.loop_id).unwrap();
+                let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
+                let ctxt = enclosing_breakables.find_breakable(destination.target_id).unwrap();
 
                 let result = if let Some(ref e) = *expr_opt {
                     // Special-case the first element, as it has no "previous expressions".
@@ -3517,8 +3533,9 @@ fn check_expr_kind(&self,
 
                 ctxt.may_break = true;
             }
-            // Otherwise, we failed to find the enclosing loop; this can only happen if the
-            // `break` was not inside a loop at all, which is caught by the loop-checking pass.
+            // Otherwise, we failed to find the enclosing breakable; this can only happen if the
+            // `break` target was not found, which is caught in HIR lowering and reported by the
+            // loop-checking pass.
             tcx.types.never
           }
           hir::ExprAgain(_) => { tcx.types.never }
@@ -3575,13 +3592,13 @@ fn check_expr_kind(&self,
           hir::ExprWhile(ref cond, ref body, _) => {
             let unified = self.tcx.mk_nil();
             let coerce_to = unified;
-            let ctxt = LoopCtxt {
+            let ctxt = BreakableCtxt {
                 unified: unified,
                 coerce_to: coerce_to,
                 break_exprs: vec![],
                 may_break: true,
             };
-            self.with_loop_ctxt(expr.id, ctxt, || {
+            self.with_breakable_ctxt(expr.id, ctxt, || {
                 self.check_expr_has_type(&cond, tcx.types.bool);
                 let cond_diverging = self.diverges.get();
                 self.check_block_no_value(&body);
@@ -3599,14 +3616,14 @@ fn check_expr_kind(&self,
           hir::ExprLoop(ref body, _, _) => {
             let unified = self.next_ty_var(TypeVariableOrigin::TypeInference(body.span));
             let coerce_to = expected.only_has_type(self).unwrap_or(unified);
-            let ctxt = LoopCtxt {
+            let ctxt = BreakableCtxt {
                 unified: unified,
                 coerce_to: coerce_to,
                 break_exprs: vec![],
                 may_break: false,
             };
 
-            let ctxt = self.with_loop_ctxt(expr.id, ctxt, || {
+            let (ctxt, ()) = self.with_breakable_ctxt(expr.id, ctxt, || {
                 self.check_block_no_value(&body);
             });
             if ctxt.may_break {
@@ -3625,8 +3642,8 @@ fn check_expr_kind(&self,
           hir::ExprClosure(capture, ref decl, body_id, _) => {
               self.check_expr_closure(expr, capture, &decl, body_id, expected)
           }
-          hir::ExprBlock(ref b) => {
-            self.check_block_with_expected(&b, expected)
+          hir::ExprBlock(ref body) => {
+            self.check_block_with_expected(&body, expected)
           }
           hir::ExprCall(ref callee, ref args) => {
               self.check_call(expr, &callee, args, expected)
@@ -3764,7 +3781,7 @@ fn check_expr_kind(&self,
             }
           }
           hir::ExprStruct(ref qpath, ref fields, ref base_expr) => {
-            self.check_expr_struct(expr, qpath, fields, base_expr)
+            self.check_expr_struct(expr, expected, qpath, fields, base_expr)
           }
           hir::ExprField(ref base, ref field) => {
             self.check_field(expr, lvalue_pref, &base, field)
@@ -4018,65 +4035,85 @@ fn check_block_with_expected(&self,
             replace(&mut *fcx_ps, unsafety_state)
         };
 
-        for s in &blk.stmts {
-            self.check_stmt(s);
-        }
+        let mut ty = if let Some(break_to_expr_id) = blk.break_to_expr_id {
+            let unified = self.next_ty_var(TypeVariableOrigin::TypeInference(blk.span));
+            let coerce_to = expected.only_has_type(self).unwrap_or(unified);
+            let ctxt = BreakableCtxt {
+                unified: unified,
+                coerce_to: coerce_to,
+                break_exprs: vec![],
+                may_break: false,
+            };
 
-        let mut ty = match blk.expr {
-            Some(ref e) => self.check_expr_with_expectation(e, expected),
-            None => self.tcx.mk_nil()
-        };
+            let (mut ctxt, (e_ty, cause)) = self.with_breakable_ctxt(break_to_expr_id, ctxt, || {
+                for s in &blk.stmts {
+                    self.check_stmt(s);
+                }
+                let coerce_to = {
+                    let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
+                    enclosing_breakables.find_breakable(
+                        hir::ScopeTarget::Block(break_to_expr_id)
+                    ).unwrap().coerce_to
+                };
+                let e_ty;
+                let cause;
+                match blk.expr {
+                    Some(ref e) => {
+                        e_ty = self.check_expr_with_hint(e, coerce_to);
+                        cause = self.misc(e.span);
+                    },
+                    None => {
+                        e_ty = self.tcx.mk_nil();
+                        cause = self.misc(blk.span);
+                    }
+                };
+
+                (e_ty, cause)
+            });
 
-        if self.diverges.get().always() {
-            ty = self.next_diverging_ty_var(TypeVariableOrigin::DivergingBlockExpr(blk.span));
-        } else if let ExpectHasType(ety) = expected {
             if let Some(ref e) = blk.expr {
-                // Coerce the tail expression to the right type.
-                self.demand_coerce(e, ty, ety);
+                let result = if !ctxt.may_break {
+                    self.try_coerce(e, e_ty, ctxt.coerce_to)
+                } else {
+                    self.try_find_coercion_lub(&cause, || ctxt.break_exprs.iter().cloned(),
+                                               ctxt.unified, e, e_ty)
+                };
+                match result {
+                    Ok(ty) => ctxt.unified = ty,
+                    Err(err) =>
+                        self.report_mismatched_types(&cause, ctxt.unified, e_ty, err).emit(),
+                }
             } else {
-                // We're not diverging and there's an expected type, which,
-                // in case it's not `()`, could result in an error higher-up.
-                // We have a chance to error here early and be more helpful.
-                let cause = self.misc(blk.span);
-                let trace = TypeTrace::types(&cause, false, ty, ety);
-                match self.sub_types(false, &cause, ty, ety) {
-                    Ok(InferOk { obligations, .. }) => {
-                        // FIXME(#32730) propagate obligations
-                        assert!(obligations.is_empty());
-                    },
-                    Err(err) => {
-                        let mut err = self.report_and_explain_type_error(trace, &err);
-
-                        // Be helpful when the user wrote `{... expr;}` and
-                        // taking the `;` off is enough to fix the error.
-                        let mut extra_semi = None;
-                        if let Some(stmt) = blk.stmts.last() {
-                            if let hir::StmtSemi(ref e, _) = stmt.node {
-                                if self.can_sub_types(self.node_ty(e.id), ety).is_ok() {
-                                    extra_semi = Some(stmt);
-                                }
-                            }
-                        }
-                        if let Some(last_stmt) = extra_semi {
-                            let original_span = original_sp(self.tcx.sess.codemap(),
-                                                            last_stmt.span, blk.span);
-                            let span_semi = Span {
-                                lo: original_span.hi - BytePos(1),
-                                hi: original_span.hi,
-                                expn_id: original_span.expn_id
-                            };
-                            err.span_help(span_semi, "consider removing this semicolon:");
-                        }
+                self.check_block_no_expr(blk, self.tcx.mk_nil(), e_ty);
+            };
 
-                        err.emit();
-                    }
-                }
+            ctxt.unified
+        } else {
+            for s in &blk.stmts {
+                self.check_stmt(s);
             }
 
-            // We already applied the type (and potentially errored),
-            // use the expected type to avoid further errors out.
-            ty = ety;
-        }
+            let mut ty = match blk.expr {
+                Some(ref e) => self.check_expr_with_expectation(e, expected),
+                None => self.tcx.mk_nil()
+            };
+
+            if self.diverges.get().always() {
+                ty = self.next_diverging_ty_var(TypeVariableOrigin::DivergingBlockExpr(blk.span));
+            } else if let ExpectHasType(ety) = expected {
+                if let Some(ref e) = blk.expr {
+                    // Coerce the tail expression to the right type.
+                    self.demand_coerce(e, ty, ety);
+                } else {
+                    self.check_block_no_expr(blk, ty, ety);
+                }
+
+                // We already applied the type (and potentially errored),
+                // use the expected type to avoid further errors out.
+                ty = ety;
+            }
+            ty
+        };
 
         if self.has_errors.get() || ty.references_error() {
             ty = self.tcx.types.err
@@ -4088,6 +4125,46 @@ fn check_block_with_expected(&self,
         ty
     }
 
+    pub fn check_block_no_expr(&self, blk: &'gcx hir::Block, ty: Ty<'tcx>, ety: Ty<'tcx>) {
+        // We're not diverging and there's an expected type, which,
+        // in case it's not `()`, could result in an error higher-up.
+        // We have a chance to error here early and be more helpful.
+        let cause = self.misc(blk.span);
+        let trace = TypeTrace::types(&cause, false, ty, ety);
+        match self.sub_types(false, &cause, ty, ety) {
+            Ok(InferOk { obligations, .. }) => {
+                // FIXME(#32730) propagate obligations
+                assert!(obligations.is_empty());
+            },
+            Err(err) => {
+                let mut err = self.report_and_explain_type_error(trace, &err);
+
+                // Be helpful when the user wrote `{... expr;}` and
+                // taking the `;` off is enough to fix the error.
+                let mut extra_semi = None;
+                if let Some(stmt) = blk.stmts.last() {
+                    if let hir::StmtSemi(ref e, _) = stmt.node {
+                        if self.can_sub_types(self.node_ty(e.id), ety).is_ok() {
+                            extra_semi = Some(stmt);
+                        }
+                    }
+                }
+                if let Some(last_stmt) = extra_semi {
+                    let original_span = original_sp(self.tcx.sess.codemap(),
+                                                    last_stmt.span, blk.span);
+                    let span_semi = Span {
+                        lo: original_span.hi - BytePos(1),
+                        hi: original_span.hi,
+                        expn_id: original_span.expn_id
+                    };
+                    err.span_help(span_semi, "consider removing this semicolon:");
+                }
+
+                err.emit();
+            }
+        }
+    }
+
     // Instantiates the given path, which must refer to an item with the given
     // number of type parameters and type.
     pub fn instantiate_value_path(&self,
@@ -4485,22 +4562,24 @@ pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
         })
     }
 
-    fn with_loop_ctxt<F: FnOnce()>(&self, id: ast::NodeId, ctxt: LoopCtxt<'gcx, 'tcx>, f: F)
-                                   -> LoopCtxt<'gcx, 'tcx> {
+    fn with_breakable_ctxt<F: FnOnce() -> R, R>(&self, id: ast::NodeId,
+                                        ctxt: BreakableCtxt<'gcx, 'tcx>, f: F)
+                                   -> (BreakableCtxt<'gcx, 'tcx>, R) {
         let index;
         {
-            let mut enclosing_loops = self.enclosing_loops.borrow_mut();
-            index = enclosing_loops.stack.len();
-            enclosing_loops.by_id.insert(id, index);
-            enclosing_loops.stack.push(ctxt);
-        }
-        f();
-        {
-            let mut enclosing_loops = self.enclosing_loops.borrow_mut();
-            debug_assert!(enclosing_loops.stack.len() == index + 1);
-            enclosing_loops.by_id.remove(&id).expect("missing loop context");
-            (enclosing_loops.stack.pop().expect("missing loop context"))
+            let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
+            index = enclosing_breakables.stack.len();
+            enclosing_breakables.by_id.insert(id, index);
+            enclosing_breakables.stack.push(ctxt);
         }
+        let result = f();
+        let ctxt = {
+            let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
+            debug_assert!(enclosing_breakables.stack.len() == index + 1);
+            enclosing_breakables.by_id.remove(&id).expect("missing breakable context");
+            enclosing_breakables.stack.pop().expect("missing breakable context")
+        };
+        (ctxt, result)
     }
 }
 
index eff848be2b8b99b2d7a6f7f3ba962dcaca120dfc..f3ea6c4467c401c396bccf1733a2494ea1040efa 100644 (file)
@@ -2241,11 +2241,11 @@ pub enum PathParameters {
     AngleBracketed {
         lifetimes: Vec<Lifetime>,
         types: Vec<Type>,
-        bindings: Vec<TypeBinding>
+        bindings: Vec<TypeBinding>,
     },
     Parenthesized {
         inputs: Vec<Type>,
-        output: Option<Type>
+        output: Option<Type>,
     }
 }
 
@@ -2260,14 +2260,14 @@ fn clean(&self, cx: &DocContext) -> PathParameters {
                         data.lifetimes.clean(cx)
                     },
                     types: data.types.clean(cx),
-                    bindings: data.bindings.clean(cx)
+                    bindings: data.bindings.clean(cx),
                 }
             }
 
             hir::ParenthesizedParameters(ref data) => {
                 PathParameters::Parenthesized {
                     inputs: data.inputs.clean(cx),
-                    output: data.output.clean(cx)
+                    output: data.output.clean(cx),
                 }
             }
         }
index fc5507d4d5559cde8ddc306560265c9bf8fe92d9..a255ba0ad4edf0b5067f0e368f399dcf82e6c83d 100644 (file)
@@ -481,7 +481,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
         if is_not_debug {
             write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
         } else {
-            write!(w, "{:?}{:?}", HRef::new(did, &last.name), last.params)?;
+            write!(w, "{:?}{}", HRef::new(did, &last.name), last.params)?;
         }
     } else {
         if is_not_debug {
@@ -507,7 +507,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
             } else {
                 format!("{:?}", HRef::new(did, &last.name))
             };
-            write!(w, "{}{:?}", path, last.params)?;
+            write!(w, "{}{}", path, last.params)?;
         }
     }
     Ok(())
index e115263d2eb9591a536f6dd88144e64f58cb41db..3d80120f6b2bd0f90d5964d21babf77860538d2f 100644 (file)
@@ -216,6 +216,11 @@ fn from(err: &'a str) -> Box<Error> {
     }
 }
 
+#[stable(feature = "never_error", since = "1.18.0")]
+impl Error for ! {
+    fn description(&self) -> &str { *self }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Error for str::ParseBoolError {
     fn description(&self) -> &str { "failed to parse bool" }
index 206a37b8e5db83e48b2e61d292b71e82bd6990d8..064144dcd68183b82bddb06d086d38ee658af447 100644 (file)
 //! [slice]: primitive.slice.html
 //! [`atomic`]: sync/atomic/index.html
 //! [`collections`]: collections/index.html
-//! [`for`]: ../book/loops.html#for
+//! [`for`]: ../book/first-edition/loops.html#for
 //! [`format!`]: macro.format.html
 //! [`fs`]: fs/index.html
 //! [`io`]: io/index.html
 //! [`sync`]: sync/index.html
 //! [`thread`]: thread/index.html
 //! [`use std::env`]: env/index.html
-//! [`use`]: ../book/crates-and-modules.html#importing-modules-with-use
-//! [crate root]: ../book/crates-and-modules.html#basic-terminology-crates-and-modules
+//! [`use`]: ../book/first-edition/crates-and-modules.html#importing-modules-with-use
+//! [crate root]: ../book/first-edition/crates-and-modules.html#basic-terminology-crates-and-modules
 //! [crates.io]: https://crates.io
-//! [deref coercions]: ../book/deref-coercions.html
+//! [deref coercions]: ../book/first-edition/deref-coercions.html
 //! [files]: fs/struct.File.html
 //! [multithreading]: thread/index.html
 //! [other]: #what-is-in-the-standard-library-documentation
-//! [primitive types]: ../book/primitive-types.html
+//! [primitive types]: ../book/first-edition/primitive-types.html
 
 #![crate_name = "std"]
 #![stable(feature = "rust1", since = "1.0.0")]
 #![feature(linkage)]
 #![feature(macro_reexport)]
 #![feature(needs_panic_runtime)]
+#![feature(never_type)]
 #![feature(num_bits_bytes)]
 #![feature(old_wrapping)]
 #![feature(on_unimplemented)]
 #![feature(placement_in_syntax)]
 #![feature(placement_new_protocol)]
 #![feature(prelude_import)]
-#![feature(pub_restricted)]
 #![feature(rand)]
 #![feature(raw)]
 #![feature(repr_simd)]
 #![feature(vec_push_all)]
 #![feature(zero_one)]
 #![cfg_attr(test, feature(update_panic_count))]
+#![cfg_attr(stage0, feature(pub_restricted))]
 
 // Explicitly import the prelude. The compiler uses this same unstable attribute
 // to import the prelude implicitly when building crates that depend on std.
index 7d6d16f4748452c70d9924d2c0a5c66f99f8d582..c738dc9440614d02fff181fd47ee83df8fd6f44c 100644 (file)
@@ -29,7 +29,7 @@
 /// ```
 ///
 /// [`assert!`]: macro.assert.html
-/// [`if`]: ../book/if.html
+/// [`if`]: ../book/first-edition/if.html
 /// [`BitAnd`]: ops/trait.BitAnd.html
 /// [`BitOr`]: ops/trait.BitOr.html
 /// [`Not`]: ops/trait.Not.html
@@ -490,7 +490,7 @@ mod prim_str { }
 /// assert_eq!(tuple.2, 'c');
 /// ```
 ///
-/// For more about tuples, see [the book](../book/primitive-types.html#tuples).
+/// For more about tuples, see [the book](../book/first-edition/primitive-types.html#tuples).
 ///
 /// # Trait implementations
 ///
index 97c48ee59034135b8cc3de89d0dfb13ea45b2c9b..7a85e58866236ad5d10d28bf7ba75ccb90f4320b 100644 (file)
@@ -343,6 +343,23 @@ pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
 
     /// Add an argument to pass to the program.
     ///
+    /// Only one argument can be passed per use. So instead of:
+    ///
+    /// ```ignore
+    /// .arg("-C /path/to/repo")
+    /// ```
+    ///
+    /// usage would be:
+    ///
+    /// ```ignore
+    /// .arg("-C")
+    /// .arg("/path/to/repo")
+    /// ```
+    ///
+    /// To pass multiple arguments see [`args`].
+    ///
+    /// [`args`]: #method.args
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -364,6 +381,10 @@ pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
 
     /// Add multiple arguments to pass to the program.
     ///
+    /// To pass a single argument see [`arg`].
+    ///
+    /// [`arg`]: #method.arg
+    ///
     /// # Examples
     ///
     /// Basic usage:
index d07069d030a1bba4099ab2887b16dccf40c54a5f..7af432176cf6ea44d0160cb0387ee577f3ea9013 100644 (file)
@@ -260,9 +260,6 @@ pub fn new() -> Features {
     // impl specialization (RFC 1210)
     (active, specialization, "1.7.0", Some(31844)),
 
-    // pub(restricted) visibilities (RFC 1422)
-    (active, pub_restricted, "1.9.0", Some(32409)),
-
     // Allow Drop types in statics/const functions (RFC 1440)
     (active, drop_types_in_const, "1.9.0", Some(33156)),
 
@@ -409,6 +406,9 @@ pub fn new() -> Features {
     (accepted, field_init_shorthand, "1.17.0", Some(37340)),
     // Allows the definition recursive static items.
     (accepted, static_recursion, "1.17.0", Some(29719)),
+    // pub(restricted) visibilities (RFC 1422)
+    (accepted, pub_restricted, "1.17.0", Some(32409)),
+
 );
 // If you change this, please modify src/doc/unstable-book as well. You must
 // move that documentation into the relevant place in the other docs, and
@@ -1417,17 +1417,6 @@ fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
         visit::walk_impl_item(self, ii);
     }
 
-    fn visit_vis(&mut self, vis: &'a ast::Visibility) {
-        let span = match *vis {
-            ast::Visibility::Crate(span) => span,
-            ast::Visibility::Restricted { ref path, .. } => path.span,
-            _ => return,
-        };
-        gate_feature_post!(&self, pub_restricted, span, "`pub(restricted)` syntax is experimental");
-
-        visit::walk_vis(self, vis)
-    }
-
     fn visit_generics(&mut self, g: &'a ast::Generics) {
         for t in &g.ty_params {
             if !t.attrs.is_empty() {
index 35e4d9eb68aeaa4d9c992dde123854ce4d6de1bd..b75b3efda36c8d8670dae90b0541797095cc0d74 100644 (file)
@@ -162,6 +162,12 @@ fn from(tt: TokenTree) -> TokenStream {
     }
 }
 
+impl From<Token> for TokenStream {
+    fn from(token: Token) -> TokenStream {
+        TokenTree::Token(DUMMY_SP, token).into()
+    }
+}
+
 impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
         TokenStream::concat(iter.into_iter().map(Into::into).collect::<Vec<_>>())
index 859fb269364623b17e092efaba3f94e70ce97c5e..d5ef27a79661d4f0d57d7b7d2cdbe9204f790a4a 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 859fb269364623b17e092efaba3f94e70ce97c5e
+Subproject commit d5ef27a79661d4f0d57d7b7d2cdbe9204f790a4a
index e89f48b4105d388f283bdd2971e5795e2e4a4f07..5ab786f40b9335aca5b7a36d5e0af99c8869e995 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #include "rustllvm.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/Instructions.h"
@@ -594,7 +595,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
     const char *LinkageName, LLVMRustMetadataRef File, unsigned LineNo,
     LLVMRustMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
     LLVMRustMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
-  Constant *InitVal = cast<Constant>(unwrap(V));
+  llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
 
 #if LLVM_VERSION_GE(4, 0)
   llvm::DIExpression *InitExpr = nullptr;
@@ -606,26 +607,21 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
     InitExpr = Builder->createConstantValueExpression(
         FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
   }
-#endif
 
-#if LLVM_VERSION_GE(4, 0)
-  return wrap(Builder->createGlobalVariableExpression(
+  llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
+      unwrapDI<DIDescriptor>(Context), Name, LinkageName,
+      unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
+      InitExpr, unwrapDIPtr<MDNode>(Decl), AlignInBits);
+
+  InitVal->setMetadata("dbg", VarExpr);
+
+  return wrap(VarExpr);
 #else
   return wrap(Builder->createGlobalVariable(
-#endif
       unwrapDI<DIDescriptor>(Context), Name, LinkageName,
       unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
-#if LLVM_VERSION_GE(4, 0)
-      InitExpr,
-#else
-      InitVal,
-#endif
-      unwrapDIPtr<MDNode>(Decl)
-#if LLVM_VERSION_GE(4, 0)
-      ,
-      AlignInBits
+      InitVal, unwrapDIPtr<MDNode>(Decl)));
 #endif
-      ));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
index aeabf4a1dd3768284138f5bc434da6f604abc654..be6d535dc732b63c606312aeb14fddaeefd5bed7 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2017-03-04
+2017-03-19
index ada1234b852a1b1c943c1b9bd92de1182fcbacbc..eb4f9e8e28e2d6a0a4c4e10224d2c29b3f298f5f 100644 (file)
@@ -30,5 +30,3 @@ fn main()
     // This should not introduce a codegen item
     let _ = cgu_generic_function::exported_but_not_generic(3);
 }
-
-//~ TRANS_ITEM drop-glue i8
index db940b680473a46606685c898f2c1f3d8d953343..d8e6028b799fbbf18be03e11ad791e98eb20befb 100644 (file)
@@ -11,8 +11,7 @@
 // ignore-tidy-linelength
 // compile-flags:-Zprint-trans-items=eager
 
-//~ TRANS_ITEM drop-glue drop_in_place_intrinsic::StructWithDtor[0]
-//~ TRANS_ITEM drop-glue-contents drop_in_place_intrinsic::StructWithDtor[0]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic.cgu-0[Internal]
 struct StructWithDtor(u32);
 
 impl Drop for StructWithDtor {
@@ -23,7 +22,7 @@ fn drop(&mut self) {}
 //~ TRANS_ITEM fn drop_in_place_intrinsic::main[0]
 fn main() {
 
-    //~ TRANS_ITEM drop-glue [drop_in_place_intrinsic::StructWithDtor[0]; 2]
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic.cgu-0[Internal]
     let x = [StructWithDtor(0), StructWithDtor(1)];
 
     drop_slice_in_place(&x);
@@ -35,7 +34,7 @@ fn drop_slice_in_place(x: &[StructWithDtor]) {
         // This is the interesting thing in this test case: Normally we would
         // not have drop-glue for the unsized [StructWithDtor]. This has to be
         // generated though when the drop_in_place() intrinsic is used.
-        //~ TRANS_ITEM drop-glue [drop_in_place_intrinsic::StructWithDtor[0]]
+        //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic.cgu-0[Internal]
         ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]);
     }
 }
index 3a9d56c2a8bf70973235695e30709ee5574314e4..c4aed7465bcb080e699fba3180ad7692486a33dd 100644 (file)
@@ -28,10 +28,12 @@ fn main() {
 
     //~ TRANS_ITEM fn function_as_argument::take_fn_once[0]<u32, &str, fn(u32, &str)>
     //~ TRANS_ITEM fn function_as_argument::function[0]<u32, &str>
+    //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0]<fn(u32, &str), (u32, &str)>
     take_fn_once(function, 0u32, "abc");
 
     //~ TRANS_ITEM fn function_as_argument::take_fn_once[0]<char, f64, fn(char, f64)>
     //~ TRANS_ITEM fn function_as_argument::function[0]<char, f64>
+    //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0]<fn(char, f64), (char, f64)>
     take_fn_once(function, 'c', 0f64);
 
     //~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0]<i32, ()>
@@ -42,5 +44,3 @@ fn main() {
     //~ TRANS_ITEM fn function_as_argument::function[0]<f32, i64>
     take_fn_pointer(function, 0f32, 0i64);
 }
-
-//~ TRANS_ITEM drop-glue i8
index 6da8154540574f9cc73616d7fa7520bc26a5f2f6..06e02b100152e3bce98a2944f4b275a6e950ed3b 100644 (file)
@@ -45,8 +45,7 @@ enum EnumNoDrop<T1, T2> {
 struct NonGenericNoDrop(i32);
 
 struct NonGenericWithDrop(i32);
-//~ TRANS_ITEM drop-glue generic_drop_glue::NonGenericWithDrop[0]
-//~ TRANS_ITEM drop-glue-contents generic_drop_glue::NonGenericWithDrop[0]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::NonGenericWithDrop[0]> @@ generic_drop_glue.cgu-0[Internal]
 
 impl Drop for NonGenericWithDrop {
     //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[2]::drop[0]
@@ -55,13 +54,11 @@ fn drop(&mut self) {}
 
 //~ TRANS_ITEM fn generic_drop_glue::main[0]
 fn main() {
-    //~ TRANS_ITEM drop-glue generic_drop_glue::StructWithDrop[0]<i8, char>
-    //~ TRANS_ITEM drop-glue-contents generic_drop_glue::StructWithDrop[0]<i8, char>
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue.cgu-0[Internal]
     //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<i8, char>
     let _ = StructWithDrop { x: 0i8, y: 'a' }.x;
 
-    //~ TRANS_ITEM drop-glue generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>
-    //~ TRANS_ITEM drop-glue-contents generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>> @@ generic_drop_glue.cgu-0[Internal]
     //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>
     let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y;
 
@@ -70,19 +67,17 @@ fn main() {
 
     // This is supposed to generate drop-glue because it contains a field that
     // needs to be dropped.
-    //~ TRANS_ITEM drop-glue generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>> @@ generic_drop_glue.cgu-0[Internal]
     let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y;
 
-    //~ TRANS_ITEM drop-glue generic_drop_glue::EnumWithDrop[0]<i32, i64>
-    //~ TRANS_ITEM drop-glue-contents generic_drop_glue::EnumWithDrop[0]<i32, i64>
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<i32, i64>> @@ generic_drop_glue.cgu-0[Internal]
     //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<i32, i64>
     let _ = match EnumWithDrop::A::<i32, i64>(0) {
         EnumWithDrop::A(x) => x,
         EnumWithDrop::B(x) => x as i32
     };
 
-    //~ TRANS_ITEM drop-glue generic_drop_glue::EnumWithDrop[0]<f64, f32>
-    //~ TRANS_ITEM drop-glue-contents generic_drop_glue::EnumWithDrop[0]<f64, f32>
+    //~TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<f64, f32>> @@ generic_drop_glue.cgu-0[Internal]
     //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<f64, f32>
     let _ = match EnumWithDrop::B::<f64, f32>(1.0) {
         EnumWithDrop::A(x) => x,
@@ -99,5 +94,3 @@ fn main() {
         EnumNoDrop::B(x) => x as f64
     };
 }
-
-//~ TRANS_ITEM drop-glue i8
index ad466671cf79bb540fbb48f03c73b9ea0f1a8c98..9c6bdb6624eaecf63c5208969f8a0a0cb007cf86 100644 (file)
@@ -31,12 +31,13 @@ fn bar(&self) {}
 fn main() {
     let s1 = Struct { _a: 0u32 };
 
-    //~ TRANS_ITEM drop-glue i8
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable.cgu-0[Internal]
     //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u32>
     //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u32>
     let _ = &s1 as &Trait;
 
     let s1 = Struct { _a: 0u64 };
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u64>> @@ instantiation_through_vtable.cgu-0[Internal]
     //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u64>
     //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u64>
     let _ = &s1 as &Trait;
index a2dcd81b6750c847a9143e08a93c2a934e8f026d..75d842d3c0bfce21cd432b49e79e83457a1558a1 100644 (file)
@@ -40,5 +40,3 @@ fn main() {
     //~ TRANS_ITEM fn items_within_generic_items::generic_fn[0]<i8>
     let _ = generic_fn(0i8);
 }
-
-//~ TRANS_ITEM drop-glue i8
index 91be81a0b8996ab81dd806deef1a102cec6e8d5b..5f70ff396ddd5f78e76220a227c81dca7d873b59 100644 (file)
@@ -13,8 +13,7 @@
 
 #![deny(dead_code)]
 
-//~ TRANS_ITEM drop-glue non_generic_drop_glue::StructWithDrop[0]
-//~ TRANS_ITEM drop-glue-contents non_generic_drop_glue::StructWithDrop[0]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue.cgu-0[Internal]
 struct StructWithDrop {
     x: i32
 }
@@ -28,8 +27,7 @@ struct StructNoDrop {
     x: i32
 }
 
-//~ TRANS_ITEM drop-glue non_generic_drop_glue::EnumWithDrop[0]
-//~ TRANS_ITEM drop-glue-contents non_generic_drop_glue::EnumWithDrop[0]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::EnumWithDrop[0]> @@ non_generic_drop_glue.cgu-0[Internal]
 enum EnumWithDrop {
     A(i32)
 }
@@ -54,5 +52,3 @@ fn main() {
         EnumNoDrop::A(x) => x
     };
 }
-
-//~ TRANS_ITEM drop-glue i8
index 4e2a7c8508468f1ac82c1d8e58e722c8b53d2f50..26f9eb11876cbe07a2d1757bbec58026a16c48c4 100644 (file)
@@ -77,5 +77,3 @@ fn main() {
     let x = Struct { _x: 0 };
     x.bar();
 }
-
-//~ TRANS_ITEM drop-glue i8
index 0295311334b6b04c73c6f3344ec678901fe2fb59..05848a727e95101c160840d9e37c7adf3c01a548 100644 (file)
@@ -68,5 +68,3 @@ fn deref(&self) -> &Self::Target {
         &self.0
     }
 }
-
-//~ TRANS_ITEM drop-glue i8
index 41c0f46f80bfb2ad4c6e22c6e40b06aa93f10c95..3c9dcf32e0c7806e07058b912de9950f8d1c897d 100644 (file)
@@ -20,4 +20,3 @@ pub fn foo<T>() { }
 fn main() { }
 
 //~ TRANS_ITEM fn static_init::main[0]
-//~ TRANS_ITEM drop-glue i8
index 7c8b2b117ef7ce51fb1bed5d26a7a66155b497e4..89bc620b7c552933226c9ad28a060329aaa23fed 100644 (file)
@@ -60,5 +60,3 @@ fn main() {
 //~ TRANS_ITEM static statics_and_consts::foo[0]::STATIC2[2]
 
 //~ TRANS_ITEM fn statics_and_consts::main[0]
-
-//~ TRANS_ITEM drop-glue i8
index 2eb2212f0cacd0f6f166d22032a2ac105149b6ff..e8a7d8f25b22ca9b89113f23242177102bebbacb 100644 (file)
@@ -78,5 +78,3 @@ fn main() {
    //~ TRANS_ITEM fn trait_implementations::{{impl}}[3]::bar[0]<&str, &str>
    0f32.bar("&str", "&str");
 }
-
-//~ TRANS_ITEM drop-glue i8
index e7006d73ef166c83c26c2d9ea5eebb1504712b7b..f095b637a84e47df7a727fe67f64267920c4e079 100644 (file)
@@ -40,23 +40,27 @@ fn take_foo_mut<T, F: FnMut(T) -> T>(mut f: F, arg: T) -> T {
 fn main() {
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0]<u32, fn(u32) -> u32>
     //~ TRANS_ITEM fn trait_method_as_argument::{{impl}}[0]::foo[0]
+    //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0]<fn(u32) -> u32, (u32)>
     take_foo_once(Trait::foo, 0u32);
 
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0]<char, fn(char) -> char>
     //~ TRANS_ITEM fn trait_method_as_argument::Trait[0]::foo[0]<char>
+    //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0]<fn(char) -> char, (char)>
     take_foo_once(Trait::foo, 'c');
 
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo[0]<u32, fn(u32) -> u32>
+    //~ TRANS_ITEM fn core::ops[0]::Fn[0]::call[0]<fn(u32) -> u32, (u32)>
     take_foo(Trait::foo, 0u32);
 
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo[0]<char, fn(char) -> char>
+    //~ TRANS_ITEM fn core::ops[0]::Fn[0]::call[0]<fn(char) -> char, (char)>
     take_foo(Trait::foo, 'c');
 
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0]<u32, fn(u32) -> u32>
+    //~ TRANS_ITEM fn core::ops[0]::FnMut[0]::call_mut[0]<fn(char) -> char, (char)>
     take_foo_mut(Trait::foo, 0u32);
 
     //~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0]<char, fn(char) -> char>
+    //~ TRANS_ITEM fn core::ops[0]::FnMut[0]::call_mut[0]<fn(u32) -> u32, (u32)>
     take_foo_mut(Trait::foo, 'c');
 }
-
-//~ TRANS_ITEM drop-glue i8
index 47892781902ea8491fbdb9063236bfc30d14166c..5b24a219f354bb140d62777f80143d726deedbfb 100644 (file)
@@ -66,5 +66,3 @@ fn main() {
     //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u32, i16, ()>
     0u32.bar(0i16, ());
 }
-
-//~ TRANS_ITEM drop-glue i8
index 81a7059fe209f4c7099fd167c600b97bc91270b0..e41cb34eec6abfd8dcfaff686d2c0474bfa094db 100644 (file)
 
 #![deny(dead_code)]
 
-//~ TRANS_ITEM drop-glue transitive_drop_glue::Root[0]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue.cgu-0[Internal]
 struct Root(Intermediate);
-//~ TRANS_ITEM drop-glue transitive_drop_glue::Intermediate[0]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Intermediate[0]> @@ transitive_drop_glue.cgu-0[Internal]
 struct Intermediate(Leaf);
-//~ TRANS_ITEM drop-glue transitive_drop_glue::Leaf[0]
-//~ TRANS_ITEM drop-glue-contents transitive_drop_glue::Leaf[0]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Leaf[0]> @@ transitive_drop_glue.cgu-0[Internal]
 struct Leaf;
 
 impl Drop for Leaf {
@@ -39,17 +38,15 @@ fn main() {
 
     let _ = Root(Intermediate(Leaf));
 
-    //~ TRANS_ITEM drop-glue transitive_drop_glue::RootGen[0]<u32>
-    //~ TRANS_ITEM drop-glue transitive_drop_glue::IntermediateGen[0]<u32>
-    //~ TRANS_ITEM drop-glue transitive_drop_glue::LeafGen[0]<u32>
-    //~ TRANS_ITEM drop-glue-contents transitive_drop_glue::LeafGen[0]<u32>
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue.cgu-0[Internal]
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<u32>> @@ transitive_drop_glue.cgu-0[Internal]
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<u32>> @@ transitive_drop_glue.cgu-0[Internal]
     //~ TRANS_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<u32>
     let _ = RootGen(IntermediateGen(LeafGen(0u32)));
 
-    //~ TRANS_ITEM drop-glue transitive_drop_glue::RootGen[0]<i16>
-    //~ TRANS_ITEM drop-glue transitive_drop_glue::IntermediateGen[0]<i16>
-    //~ TRANS_ITEM drop-glue transitive_drop_glue::LeafGen[0]<i16>
-    //~ TRANS_ITEM drop-glue-contents transitive_drop_glue::LeafGen[0]<i16>
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<i16>> @@ transitive_drop_glue.cgu-0[Internal]
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<i16>> @@ transitive_drop_glue.cgu-0[Internal]
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue.cgu-0[Internal]
     //~ TRANS_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<i16>
     let _ = RootGen(IntermediateGen(LeafGen(0i16)));
 }
index ef4bc1dca594cc6174d0aa355841df65cbb2e987..39043cf87cbecd7bd838ba8e71df4e0e785f8acf 100644 (file)
@@ -13,8 +13,7 @@
 
 #![deny(dead_code)]
 
-//~ TRANS_ITEM drop-glue tuple_drop_glue::Dropped[0]
-//~ TRANS_ITEM drop-glue-contents tuple_drop_glue::Dropped[0]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue.cgu-0[Internal]
 struct Dropped;
 
 impl Drop for Dropped {
@@ -24,10 +23,10 @@ fn drop(&mut self) {}
 
 //~ TRANS_ITEM fn tuple_drop_glue::main[0]
 fn main() {
-    //~ TRANS_ITEM drop-glue (u32, tuple_drop_glue::Dropped[0])
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue.cgu-0[Internal]
     let x = (0u32, Dropped);
 
-    //~ TRANS_ITEM drop-glue (i16, (tuple_drop_glue::Dropped[0], bool))
-    //~ TRANS_ITEM drop-glue (tuple_drop_glue::Dropped[0], bool)
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue.cgu-0[Internal]
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue.cgu-0[Internal]
     let x = (0i16, (Dropped, true));
 }
index cd4cc258f7a682edbbaa4a30cfa263fa55d670f3..de7613741b27bfd2610dbe87184d29195f47d3f4 100644 (file)
@@ -57,11 +57,13 @@ fn main()
 {
     // simple case
     let bool_sized = &true;
-    //~ TRANS_ITEM drop-glue i8
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<bool> @@ unsizing.cgu-0[Internal]
     //~ TRANS_ITEM fn unsizing::{{impl}}[0]::foo[0]
     let _bool_unsized = bool_sized as &Trait;
 
-    let char_sized = &true;
+    let char_sized = &'a';
+
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<char> @@ unsizing.cgu-0[Internal]
     //~ TRANS_ITEM fn unsizing::{{impl}}[1]::foo[0]
     let _char_unsized = char_sized as &Trait;
 
@@ -71,11 +73,13 @@ fn main()
         _b: 2,
         _c: 3.0f64
     };
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<f64> @@ unsizing.cgu-0[Internal]
     //~ TRANS_ITEM fn unsizing::{{impl}}[2]::foo[0]
     let _struct_unsized = struct_sized as &Struct<Trait>;
 
     // custom coercion
     let wrapper_sized = Wrapper(&0u32);
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ unsizing.cgu-0[Internal]
     //~ TRANS_ITEM fn unsizing::{{impl}}[3]::foo[0]
     let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
 }
index 8689beb3fb77e98e6df3cc05214d348615f01134..ce85c4fc13ce2a753b38961b6a2dd22eedc9e430 100644 (file)
@@ -86,4 +86,3 @@ pub fn generic_bar<T: Copy>(x: T) -> (T, T) {
 
 // Only the non-generic methods should be instantiated:
 //~ TRANS_ITEM fn unused_traits_and_generics::{{impl}}[3]::foo[0]
-//~ TRANS_ITEM drop-glue i8
index 910ffd2959ed089400ec7691b95710e808db1631..f28c4872111c990c3e89684c599b8d5d46f4ec09 100644 (file)
 // aux-build:cgu_extern_drop_glue.rs
 extern crate cgu_extern_drop_glue;
 
-//~ TRANS_ITEM drop-glue cgu_extern_drop_glue::Struct[0] @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
-//~ TRANS_ITEM drop-glue-contents cgu_extern_drop_glue::Struct[0] @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
 
 struct LocalStruct(cgu_extern_drop_glue::Struct);
 
 //~ TRANS_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External]
 fn user()
 {
-    //~ TRANS_ITEM drop-glue extern_drop_glue::LocalStruct[0] @@ extern_drop_glue[Internal]
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
     let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
 }
 
@@ -40,7 +39,7 @@ mod mod1 {
     //~ TRANS_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External]
     fn user()
     {
-        //~ TRANS_ITEM drop-glue extern_drop_glue::mod1[0]::LocalStruct[0] @@ extern_drop_glue-mod1[Internal]
+        //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
         let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
     }
 }
index db36b50702a43efd090be185914bddd167dd9527..e32c946f8554f4ca5c6ac5c9d1b86235fd027267 100644 (file)
@@ -60,5 +60,3 @@ fn non_user() {}
 // once for the current crate
 //~ TRANS_ITEM fn cgu_generic_function::foo[0]<&str> @@ cgu_generic_function.volatile[External]
 //~ TRANS_ITEM fn cgu_generic_function::bar[0]<&str> @@ cgu_generic_function.volatile[External]
-
-//~ TRANS_ITEM drop-glue i8
index f61e3fe12931e0ddb6041ca5d240f3f804b01236..64f4f854c2d7ffe00db0d576dd9495c6b8e2191e 100644 (file)
@@ -16,8 +16,7 @@
 #![allow(dead_code)]
 #![crate_type="lib"]
 
-//~ TRANS_ITEM drop-glue local_drop_glue::Struct[0] @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
-//~ TRANS_ITEM drop-glue-contents local_drop_glue::Struct[0] @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
 struct Struct {
     _a: u32
 }
@@ -27,7 +26,7 @@ impl Drop for Struct {
     fn drop(&mut self) {}
 }
 
-//~ TRANS_ITEM drop-glue local_drop_glue::Outer[0] @@ local_drop_glue[Internal]
+//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal]
 struct Outer {
     _a: Struct
 }
@@ -46,10 +45,10 @@ mod mod1
 {
     use super::Struct;
 
-    //~ TRANS_ITEM drop-glue local_drop_glue::mod1[0]::Struct2[0] @@ local_drop_glue-mod1[Internal]
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal]
     struct Struct2 {
         _a: Struct,
-        //~ TRANS_ITEM drop-glue (u32, local_drop_glue::Struct[0]) @@ local_drop_glue-mod1[Internal]
+        //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal]
         _b: (u32, Struct),
     }
 
index 4da64110321688400ba7b734460abd4b5e344ada..07c341203f9e206a0ef17098be4cd0abffcdbcde 100644 (file)
@@ -80,5 +80,3 @@ fn bar() {}
         static BAZ: u64 = 0;
     }
 }
-
-//~ TRANS_ITEM drop-glue i8
index ffe1ec278b8dd3e0b99075d4bf615a9acfec2b69..d06b3ac407a7f4d2898d2d97cc006f0ced6bcb61 100644 (file)
@@ -46,5 +46,3 @@ fn function() {
         static BAR: u32 = 0;
     }
 }
-
-//~ TRANS_ITEM drop-glue i8
index 7a0217072f32c597cd44011f191f4bbaf7dff69d..c4594bb547ef54ba303b4777e85c1b80a4a0f430 100644 (file)
@@ -69,7 +69,7 @@ fn do_something_else(&self, x: T) -> T { x }
 
 //~ TRANS_ITEM fn vtable_through_const::main[0] @@ vtable_through_const[External]
 fn main() {
-    //~ TRANS_ITEM drop-glue i8 @@ vtable_through_const[Internal]
+    //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ vtable_through_const[Internal]
 
     // Since Trait1::do_something() is instantiated via its default implementation,
     // it is considered a generic and is instantiated here only because it is
index 6f458da9b527ba861e1f330e77acb4e9771a2e7b..dfbe35dfd56ba2e68a01fc90ea5b41c7b1858355 100644 (file)
@@ -35,7 +35,6 @@
 // non-pub fields, marked with SILLY below)
 
 #![feature(staged_api)]
-#![feature(pub_restricted)]
 
 #![stable(feature = "unit_test", since = "0.0.0")]
 
diff --git a/src/test/compile-fail/catch-bad-lifetime.rs b/src/test/compile-fail/catch-bad-lifetime.rs
new file mode 100644 (file)
index 0000000..57242da
--- /dev/null
@@ -0,0 +1,43 @@
+// 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(catch_expr)]
+
+// This test checks that borrows made and returned inside catch blocks are properly constrained
+pub fn main() {
+    {
+        // Test that borrows returned from a catch block must be valid for the lifetime of the
+        // result variable
+        let _result: Result<(), &str> = do catch {
+            let my_string = String::from("");
+            let my_str: & str = & my_string;
+            Err(my_str) ?;
+            Err("") ?;
+            Ok(())
+        }; //~ ERROR `my_string` does not live long enough
+    }
+
+    {
+        // Test that borrows returned from catch blocks freeze their referent
+        let mut i = 5;
+        let k = &mut i;
+        let mut j: Result<(), &mut i32> = do catch {
+            Err(k) ?;
+            i = 10; //~ ERROR cannot assign to `i` because it is borrowed
+            Ok(())
+        };
+        ::std::mem::drop(k); //~ ERROR use of moved value: `k`
+        i = 40; //~ ERROR cannot assign to `i` because it is borrowed
+
+        let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
+        *i_ptr = 50;
+    }
+}
+
diff --git a/src/test/compile-fail/catch-bad-type.rs b/src/test/compile-fail/catch-bad-type.rs
new file mode 100644 (file)
index 0000000..cff9f50
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(catch_expr)]
+
+pub fn main() {
+    let res: Result<i32, i32> = do catch {
+        Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` is not satisfied
+        Ok(5)
+    };
+    let res: Result<i32, i32> = do catch {
+        Ok("") //~ mismatched types
+    };
+}
diff --git a/src/test/compile-fail/catch-maybe-bad-lifetime.rs b/src/test/compile-fail/catch-maybe-bad-lifetime.rs
new file mode 100644 (file)
index 0000000..b783a3d
--- /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.
+
+#![feature(catch_expr)]
+
+// This test checks that borrows made and returned inside catch blocks are properly constrained
+pub fn main() {
+    {
+        // Test that a borrow which *might* be returned still freezes its referent
+        let mut i = 222;
+        let x: Result<&i32, ()> = do catch {
+            Err(())?;
+            Ok(&i)
+        };
+        x.ok().cloned();
+        i = 0; //~ ERROR cannot assign to `i` because it is borrowed
+        let _ = i;
+    }
+
+    {
+        let x = String::new();
+        let _y: Result<(), ()> = do catch {
+            Err(())?;
+            ::std::mem::drop(x);
+            Ok(())
+        };
+        println!("{}", x); //~ ERROR use of moved value: `x`
+    }
+
+    {
+        // Test that a borrow which *might* be assigned to an outer variable still freezes
+        // its referent
+        let mut i = 222;
+        let j;
+        let x: Result<(), ()> = do catch {
+            Err(())?;
+            j = &i;
+            Ok(())
+        };
+        i = 0; //~ ERROR cannot assign to `i` because it is borrowed
+        let _ = i;
+    }
+}
+
diff --git a/src/test/compile-fail/catch-opt-init.rs b/src/test/compile-fail/catch-opt-init.rs
new file mode 100644 (file)
index 0000000..48284b4
--- /dev/null
@@ -0,0 +1,26 @@
+// 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(catch_expr)]
+
+fn use_val<T: Sized>(_x: T) {}
+
+pub fn main() {
+    let cfg_res;
+    let _: Result<(), ()> = do catch {
+        Err(())?;
+        cfg_res = 5;
+        Ok::<(), ()>(())?;
+        use_val(cfg_res);
+        Ok(())
+    };
+    assert_eq!(cfg_res, 5); //~ ERROR use of possibly uninitialized variable
+}
+
index 05ecc781af30d53b22689e613d3ab4ca74eb8351..1eb756fe9e4ec2bd258f9725c2e440bbc90e7b7d 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
 #![deny(unused)]
 
 mod foo {
index b1c88ce6ce55c796d731e41b910353d7b3bbf2fa..82d14ddb502b3e726430203860129fc8b7c37978 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
-
 pub(crate) struct Crate;
 #[derive(Default)]
 pub struct Universe {
diff --git a/src/test/compile-fail/privacy/restricted/feature-gate.rs b/src/test/compile-fail/privacy/restricted/feature-gate.rs
deleted file mode 100644 (file)
index e81e1e3..0000000
+++ /dev/null
@@ -1,27 +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.
-
-// gate-test-pub_restricted
-
-pub(crate) //~ ERROR experimental
-mod foo {}
-
-pub(self) //~ ERROR experimental
-mod bar {}
-
-struct S {
-    pub(self) x: i32, //~ ERROR experimental
-}
-impl S {
-    pub(self) fn f() {} //~ ERROR experimental
-}
-extern {
-    pub(self) fn f(); //~ ERROR experimental
-}
index 2d4b5545544c68556c2408360abf6be5c39326e8..abd71b9c90b22ac357267a33f6995cc8acd58e2c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_attrs, pub_restricted)]
+#![feature(rustc_attrs)]
 #![allow(warnings)]
 
 mod foo {
index 84328ca387d73dd94053602454f31f6f5ee2d744..0fdfbaa84bb5a425a0e8d7b4108cc17098efdc74 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
-
 mod foo {
     struct Priv;
     mod bar {
index 53786d45c73ee36a2773d314348cd5558788236e..68458fe3f04ba6f1a23c35864e7133b0267c7604 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
 #![deny(private_in_public)]
 #![allow(warnings)]
 
index d55ee8221cd733f96c4b672b9610951c04f95088..12697d51042edff24e2ca68778c9d1dde277a3f4 100644 (file)
@@ -10,7 +10,6 @@
 
 // aux-build:pub_restricted.rs
 
-#![feature(pub_restricted)]
 #![deny(private_in_public)]
 #![allow(warnings)]
 extern crate pub_restricted;
index f3dcf405a68a6276abc0e99abc36df62e5baef40..bb212b3114d11e8a46323d5433931aebe0d6b7e9 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
-
 mod foo {
     type T = ();
     struct S1(pub(foo) (), pub(T), pub(crate) (), pub(((), T)));
index 3bf8ca30a6c3fe42df1b46936704d56cdce21c24..2c6e71d7c55e6af64fed081e4eb082de602fcf4c 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
-
 macro_rules! define_struct {
     ($t:ty) => {
         struct S1(pub $t);
index febe224fb84dcf14ce2294d6b1940109b13e9843..e15eeae8159a363983790cfdcebc381793e75731 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
-
 macro_rules! define_struct {
     ($t:ty) => {
         struct S1(pub($t));
index cd0edc8fe7c4414775f91973b52877f5da9ee38f..c83a4e568528fe8454bbd6a70295ccda9a068612 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
-
 macro_rules! m {
     ($p: path) => (pub(in $p) struct Z;)
 }
index 4924fabafb0a0ee465be0c1991e26e3436b0e54c..bddcd391b205d5e80263f3c65a548abf12c57608 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
 #![feature(untagged_unions)]
 
 mod m {
index 7151538f412568893dfab75a11a1636c594ac923..e26b5e99ec1a5f62167df2846561ebeec0b7c43d 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
 #![feature(untagged_unions)]
 
 mod m {
index 20878a91ede9907d88c2f178a7f8b9672261e14b..420a45a2147e6b94fba4cac5cbcb50efb89a0efa 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
-
 enum E {}
 trait Tr {}
 
index 2f94a440e72da3ca5342883acb0d1660ce27e28c..0433b95865ef8c4591479fb9a660d93fd8b38ce2 100644 (file)
@@ -49,9 +49,10 @@ fn cond(input: TokenStream) -> TokenStream {
             _ => false,
         };
         conds.push(if is_else || input.peek().is_none() {
-            qquote!({ unquote rhs })
+            quote!({ $rhs })
         } else {
-            qquote!(if unquote(test.unwrap()) { unquote rhs } else)
+            let test = test.unwrap();
+            quote!(if $test { $rhs } else)
         });
     }
 
index 91075276a302039d221fc5d648de642231f245a4..9522592a5e9e6642d79c072bf873c78e78770682 100644 (file)
@@ -29,6 +29,11 @@ pub fn plugin_registrar(reg: &mut Registry) {
 
 // This macro is not very interesting, but it does contain delimited tokens with
 // no content - `()` and `{}` - which has caused problems in the past.
+// Also, it tests that we can escape `$` via `$$`.
 fn hello(_: TokenStream) -> TokenStream {
-    qquote!({ fn hello() {} hello(); })
+    quote!({
+        fn hello() {}
+        macro_rules! m { ($$($$t:tt)*) => { $$($$t)* } }
+        m!(hello());
+    })
 }
index 612c199e8281a1a02909481ad31620aa979619fb..0e37a7a5dcce22f8daf5d603513812ac44c0689b 100644 (file)
@@ -34,21 +34,21 @@ pub fn plugin_registrar(reg: &mut Registry) {
 }
 
 fn attr_tru(_attr: TokenStream, _item: TokenStream) -> TokenStream {
-    qquote!(fn f1() -> bool { true })
+    quote!(fn f1() -> bool { true })
 }
 
 fn attr_identity(_attr: TokenStream, item: TokenStream) -> TokenStream {
-    qquote!(unquote item)
+    quote!($item)
 }
 
 fn tru(_ts: TokenStream) -> TokenStream {
-    qquote!(true)
+    quote!(true)
 }
 
 fn ret_tru(_ts: TokenStream) -> TokenStream {
-    qquote!(return true;)
+    quote!(return true;)
 }
 
 fn identity(ts: TokenStream) -> TokenStream {
-    qquote!(unquote ts)
+    quote!($ts)
 }
index 57b6c3f0adb89723c77851cee84ada3b7378a426..01b0ed802354c74e19f15f217738caa7bf50a685 100644 (file)
@@ -22,6 +22,6 @@
 use syntax::tokenstream::TokenTree;
 
 fn main() {
-    let true_tok = TokenTree::Token(syntax_pos::DUMMY_SP, token::Ident(Ident::from_str("true")));
-    assert!(qquote!(true).eq_unspanned(&true_tok.into()));
+    let true_tok = token::Ident(Ident::from_str("true"));
+    assert!(quote!(true).eq_unspanned(&true_tok.into()));
 }
diff --git a/src/test/run-pass-fulldeps/macro-quote-empty-delims.rs b/src/test/run-pass-fulldeps/macro-quote-empty-delims.rs
deleted file mode 100644 (file)
index bdbea8a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that a macro can emit delimiters with nothing inside - `()`, `{}`
-
-// aux-build:hello_macro.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![feature(rustc_private)]
-#![plugin(hello_macro)]
-
-fn main() {
-    hello!();
-}
diff --git a/src/test/run-pass-fulldeps/macro-quote-test.rs b/src/test/run-pass-fulldeps/macro-quote-test.rs
new file mode 100644 (file)
index 0000000..bdbea8a
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that a macro can emit delimiters with nothing inside - `()`, `{}`
+
+// aux-build:hello_macro.rs
+// ignore-stage1
+
+#![feature(plugin)]
+#![feature(rustc_private)]
+#![plugin(hello_macro)]
+
+fn main() {
+    hello!();
+}
index a9b28a534a3483edd4b69a98f00bcfd0f309f6dc..5a757161a78a4e6858e4d6bf7e4717c67d861d23 100644 (file)
@@ -29,4 +29,46 @@ pub fn main() {
     match catch {
         _ => {}
     };
+
+    let catch_err = do catch {
+        Err(22)?;
+        Ok(1)
+    };
+    assert_eq!(catch_err, Err(22));
+
+    let catch_okay: Result<i32, i32> = do catch {
+        if false { Err(25)?; }
+        Ok::<(), i32>(())?;
+        Ok(28)
+    };
+    assert_eq!(catch_okay, Ok(28));
+
+    let catch_from_loop: Result<i32, i32> = do catch {
+        for i in 0..10 {
+            if i < 5 { Ok::<i32, i32>(i)?; } else { Err(i)?; }
+        }
+        Ok(22)
+    };
+    assert_eq!(catch_from_loop, Err(5));
+
+    let cfg_init;
+    let _res: Result<(), ()> = do catch {
+        cfg_init = 5;
+        Ok(())
+    };
+    assert_eq!(cfg_init, 5);
+
+    let cfg_init_2;
+    let _res: Result<(), ()> = do catch {
+        cfg_init_2 = 6;
+        Err(())?;
+        Ok(())
+    };
+    assert_eq!(cfg_init_2, 6);
+
+    let my_string = "test".to_string();
+    let res: Result<&str, ()> = do catch {
+        Ok(&my_string)
+    };
+    assert_eq!(res, Ok("test"));
 }
index 2a7a593d26800fd322d77a2ede4ba29960089d44..cef2f879f9cd74bc69c1209713fdda0ab1a4f48a 100644 (file)
@@ -160,6 +160,34 @@ pub fn main() {
     t!(format!("{:?}", -0.0), "-0");
     t!(format!("{:?}", 0.0), "0");
 
+    // sign aware zero padding
+    t!(format!("{:<3}", 1), "1  ");
+    t!(format!("{:>3}", 1), "  1");
+    t!(format!("{:^3}", 1), " 1 ");
+    t!(format!("{:03}", 1), "001");
+    t!(format!("{:<03}", 1), "001");
+    t!(format!("{:>03}", 1), "001");
+    t!(format!("{:^03}", 1), "001");
+    t!(format!("{:+03}", 1), "+01");
+    t!(format!("{:<+03}", 1), "+01");
+    t!(format!("{:>+03}", 1), "+01");
+    t!(format!("{:^+03}", 1), "+01");
+    t!(format!("{:#05x}", 1), "0x001");
+    t!(format!("{:<#05x}", 1), "0x001");
+    t!(format!("{:>#05x}", 1), "0x001");
+    t!(format!("{:^#05x}", 1), "0x001");
+    t!(format!("{:05}", 1.2), "001.2");
+    t!(format!("{:<05}", 1.2), "001.2");
+    t!(format!("{:>05}", 1.2), "001.2");
+    t!(format!("{:^05}", 1.2), "001.2");
+    t!(format!("{:05}", -1.2), "-01.2");
+    t!(format!("{:<05}", -1.2), "-01.2");
+    t!(format!("{:>05}", -1.2), "-01.2");
+    t!(format!("{:^05}", -1.2), "-01.2");
+    t!(format!("{:+05}", 1.2), "+01.2");
+    t!(format!("{:<+05}", 1.2), "+01.2");
+    t!(format!("{:>+05}", 1.2), "+01.2");
+    t!(format!("{:^+05}", 1.2), "+01.2");
 
     // Ergonomic format_args!
     t!(format!("{0:x} {0:X}", 15), "f F");
index ec2b53313faa79be4c062f3f704c6978a449eff7..281dde15bd336e4d45a2022e6c158e1db3e71aa1 100644 (file)
@@ -8,6 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::panic;
+
+impl<'a> panic::UnwindSafe for Foo<'a> {}
+impl<'a> panic::RefUnwindSafe for Foo<'a> {}
+
 struct Foo<'a>(&'a mut bool);
 
 impl<'a> Drop for Foo<'a> {
@@ -28,5 +33,15 @@ fn main() {
         f(x);
     }
     assert!(ran_drop);
-}
 
+    let mut ran_drop = false;
+    {
+        let x = Foo(&mut ran_drop);
+        let result = panic::catch_unwind(move || {
+            let x = move || { let _ = x; panic!() };
+            f(x);
+        });
+        assert!(result.is_err());
+    }
+    assert!(ran_drop);
+}
diff --git a/src/test/run-pass/issue-31260.rs b/src/test/run-pass/issue-31260.rs
new file mode 100644 (file)
index 0000000..e771fc7
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+pub struct Struct<K: 'static> {
+    pub field: K,
+}
+
+// Partial fix for #31260, doesn't work without {...}.
+static STRUCT: Struct<&'static [u8]> = Struct {
+    field: {&[1]}
+};
+
+fn main() {}
diff --git a/src/test/run-pass/mir_calls_to_shims.rs b/src/test/run-pass/mir_calls_to_shims.rs
new file mode 100644 (file)
index 0000000..7300a32
--- /dev/null
@@ -0,0 +1,56 @@
+// 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(fn_traits)]
+#![feature(never_type)]
+
+use std::panic;
+
+fn foo(x: u32, y: u32) -> u32 { x/y }
+fn foo_diverges() -> ! { panic!() }
+
+fn test_fn_ptr<T>(mut t: T)
+    where T: Fn(u32, u32) -> u32,
+{
+    let as_fn = <T as Fn<(u32, u32)>>::call;
+    assert_eq!(as_fn(&t, (9, 3)), 3);
+    let as_fn_mut = <T as FnMut<(u32, u32)>>::call_mut;
+    assert_eq!(as_fn_mut(&mut t, (18, 3)), 6);
+    let as_fn_once = <T as FnOnce<(u32, u32)>>::call_once;
+    assert_eq!(as_fn_once(t, (24, 3)), 8);
+}
+
+fn assert_panics<F>(f: F) where F: FnOnce() {
+    let f = panic::AssertUnwindSafe(f);
+    let result = panic::catch_unwind(move || {
+        f.0()
+    });
+    if let Ok(..) = result {
+        panic!("diverging function returned");
+    }
+}
+
+fn test_fn_ptr_panic<T>(mut t: T)
+    where T: Fn() -> !
+{
+    let as_fn = <T as Fn<()>>::call;
+    assert_panics(|| as_fn(&t, ()));
+    let as_fn_mut = <T as FnMut<()>>::call_mut;
+    assert_panics(|| as_fn_mut(&mut t, ()));
+    let as_fn_once = <T as FnOnce<()>>::call_once;
+    assert_panics(|| as_fn_once(t, ()));
+}
+
+fn main() {
+    test_fn_ptr(foo);
+    test_fn_ptr(foo as fn(u32, u32) -> u32);
+    test_fn_ptr_panic(foo_diverges);
+    test_fn_ptr_panic(foo_diverges as fn() -> !);
+}
diff --git a/src/test/rustdoc/const-doc.rs b/src/test/rustdoc/const-doc.rs
new file mode 100644 (file)
index 0000000..9f70fe4
--- /dev/null
@@ -0,0 +1,31 @@
+// 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(associated_consts)]
+
+use std::marker::PhantomData;
+
+pub struct Foo<'a> {
+    f: PhantomData<&'a u32>,
+}
+
+pub struct ContentType {
+    pub ttype: Foo<'static>,
+    pub subtype: Foo<'static>,
+    pub params: Option<Foo<'static>>,
+}
+
+impl ContentType {
+    // @has const_doc/struct.ContentType.html
+    // @has  - '//*[@class="docblock"]' 'Any: ContentType = ContentType{ttype: Foo{f: '
+    pub const Any: ContentType = ContentType { ttype: Foo { f: PhantomData, },
+                                               subtype: Foo { f: PhantomData, },
+                                               params: None, };
+}
index 383224b2f92737ac886c22f726abb5d18173bb52..704b20c6e712e588c65d027e970753d13862e3c4 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted)]
-
 pub mod m {
     pub struct S(u8);
 
index 68bd74719f55cdadcac6d7384040706f467e1e9e..87e7b4f42a1c027917fc41e3085b6b81b92c297c 100644 (file)
@@ -10,8 +10,6 @@
 
 // aux-build:privacy-struct-ctor.rs
 
-#![feature(pub_restricted)]
-
 extern crate privacy_struct_ctor as xcrate;
 
 mod m {
index 30fdbb02cc71522101be52b443dbd7b1cb697e4b..25afb6147e422d49fd6ff5163ce99076d2b0cb62 100644 (file)
@@ -1,7 +1,7 @@
 error[E0423]: expected value, found struct `Z`
-  --> $DIR/privacy-struct-ctor.rs:28:9
+  --> $DIR/privacy-struct-ctor.rs:26:9
    |
-28 |         Z;
+26 |         Z;
    |         ^
    |         |
    |         did you mean `Z { /* fields */ }`?
@@ -11,9 +11,9 @@ error[E0423]: expected value, found struct `Z`
              `use m::n::Z;`
 
 error[E0423]: expected value, found struct `S`
-  --> $DIR/privacy-struct-ctor.rs:38:5
+  --> $DIR/privacy-struct-ctor.rs:36:5
    |
-38 |     S;
+36 |     S;
    |     ^
    |     |
    |     did you mean `S { /* fields */ }`?
@@ -23,9 +23,9 @@ error[E0423]: expected value, found struct `S`
              `use m::S;`
 
 error[E0423]: expected value, found struct `xcrate::S`
-  --> $DIR/privacy-struct-ctor.rs:44:5
+  --> $DIR/privacy-struct-ctor.rs:42:5
    |
-44 |     xcrate::S;
+42 |     xcrate::S;
    |     ^^^^^^^^^
    |     |
    |     did you mean `xcrate::S { /* fields */ }`?
@@ -35,33 +35,33 @@ error[E0423]: expected value, found struct `xcrate::S`
              `use m::S;`
 
 error: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:27:9
+  --> $DIR/privacy-struct-ctor.rs:25:9
    |
-27 |         n::Z; //~ ERROR tuple struct `Z` is private
+25 |         n::Z; //~ ERROR tuple struct `Z` is private
    |         ^^^^
 
 error: tuple struct `S` is private
-  --> $DIR/privacy-struct-ctor.rs:37:5
+  --> $DIR/privacy-struct-ctor.rs:35:5
    |
-37 |     m::S; //~ ERROR tuple struct `S` is private
+35 |     m::S; //~ ERROR tuple struct `S` is private
    |     ^^^^
 
 error: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:41:5
+  --> $DIR/privacy-struct-ctor.rs:39:5
    |
-41 |     m::n::Z; //~ ERROR tuple struct `Z` is private
+39 |     m::n::Z; //~ ERROR tuple struct `Z` is private
    |     ^^^^^^^
 
 error: tuple struct `S` is private
-  --> $DIR/privacy-struct-ctor.rs:43:5
+  --> $DIR/privacy-struct-ctor.rs:41:5
    |
-43 |     xcrate::m::S; //~ ERROR tuple struct `S` is private
+41 |     xcrate::m::S; //~ ERROR tuple struct `S` is private
    |     ^^^^^^^^^^^^
 
 error: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:47:5
+  --> $DIR/privacy-struct-ctor.rs:45:5
    |
-47 |     xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+45 |     xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
    |     ^^^^^^^^^^^^^^^
 
 error: aborting due to 8 previous errors
index 9f8f871200ca5543a0d1e33a319fb180d3479463..54cb0b59c75c3450f3979d7cb5dbb27b2a1e0d3d 100644 (file)
@@ -11,8 +11,6 @@
 // Regression test for issue #26083 and #35435
 // Test that span for public struct fields start at `pub`
 
-#![feature(pub_restricted)]
-
 struct Foo {
     bar: u8,
     pub bar: u8,
index 2c002c34736c54bca4bbd25d93f37c5a6e8cb192..c66361c8546b839046fb47b9fcf2556eeba2c395 100644 (file)
@@ -1,18 +1,18 @@
 error[E0124]: field `bar` is already declared
-  --> $DIR/pub-struct-field.rs:18:5
+  --> $DIR/pub-struct-field.rs:16:5
    |
-17 |     bar: u8,
+15 |     bar: u8,
    |     ------- `bar` first declared here
-18 |     pub bar: u8,
+16 |     pub bar: u8,
    |     ^^^^^^^^^^^ field already declared
 
 error[E0124]: field `bar` is already declared
-  --> $DIR/pub-struct-field.rs:19:5
+  --> $DIR/pub-struct-field.rs:17:5
    |
-17 |     bar: u8,
+15 |     bar: u8,
    |     ------- `bar` first declared here
-18 |     pub bar: u8,
-19 |     pub(crate) bar: u8,
+16 |     pub bar: u8,
+17 |     pub(crate) bar: u8,
    |     ^^^^^^^^^^^^^^^^^^ field already declared
 
 error: aborting due to 2 previous errors
index ba5ca44526b86340be3209a2233d7dbd5324a58f..8c4eb728b7561d5bdd026cf06273660cc08aaabe 100644 (file)
@@ -122,6 +122,12 @@ fn check(cache: &mut Cache,
         return None;
     }
 
+    // ignore handlebars files as they use {{}} to build links, we only
+    // want to test the generated files
+    if file.extension().and_then(|s| s.to_str()) == Some("hbs") {
+        return None;
+    }
+
     // Unfortunately we're not 100% full of valid links today to we need a few
     // whitelists to get this past `make check` today.
     // FIXME(#32129)