]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #11598 : alexcrichton/rust/io-export, r=brson
authorbors <bors@rust-lang.org>
Fri, 17 Jan 2014 20:02:07 +0000 (12:02 -0800)
committerbors <bors@rust-lang.org>
Fri, 17 Jan 2014 20:02:07 +0000 (12:02 -0800)
* Reexport io::mem and io::buffered structs directly under io, make mem/buffered
  private modules
* Remove with_mem_writer
* Remove DEFAULT_CAPACITY and use DEFAULT_BUF_SIZE (in io::buffered)

cc #11119

232 files changed:
Makefile.in
configure
doc/README.md
doc/index.md
doc/po/ja/complement-cheatsheet.md.po [new file with mode: 0644]
doc/po/ja/complement-lang-faq.md.po [new file with mode: 0644]
doc/po/ja/complement-project-faq.md.po [new file with mode: 0644]
doc/po/ja/guide-conditions.md.po [new file with mode: 0644]
doc/po/ja/guide-container.md.po [new file with mode: 0644]
doc/po/ja/guide-ffi.md.po [new file with mode: 0644]
doc/po/ja/guide-lifetimes.md.po [new file with mode: 0644]
doc/po/ja/guide-macros.md.po [new file with mode: 0644]
doc/po/ja/guide-pointers.md.po [new file with mode: 0644]
doc/po/ja/guide-rustpkg.md.po [new file with mode: 0644]
doc/po/ja/guide-tasks.md.po [new file with mode: 0644]
doc/po/ja/guide-testing.md.po [new file with mode: 0644]
doc/po/ja/index.md.po [new file with mode: 0644]
doc/po/ja/rust.md.po
doc/po/ja/rustdoc.md.po [new file with mode: 0644]
doc/po/ja/rustpkg.md.po
doc/po/ja/tutorial-borrowed-ptr.md.po [deleted file]
doc/po/ja/tutorial-container.md.po [deleted file]
doc/po/ja/tutorial-ffi.md.po [deleted file]
doc/po/ja/tutorial-macros.md.po [deleted file]
doc/po/ja/tutorial-tasks.md.po [deleted file]
doc/po/ja/tutorial.md.po
doc/rust.md
mk/host.mk
mk/llvm.mk
mk/tests.mk
src/compiletest/header.rs
src/etc/check-summary.py
src/etc/vim/syntax/rust.vim
src/libextra/base64.rs
src/libextra/comm.rs
src/libextra/ebml.rs
src/libextra/enum_set.rs
src/libextra/hex.rs
src/libextra/lib.rs
src/libextra/num/bigint.rs
src/libextra/sync.rs
src/libextra/test.rs
src/libextra/time.rs
src/libgreen/macros.rs
src/libgreen/sched.rs
src/libnative/bookeeping.rs [deleted file]
src/libnative/bookkeeping.rs [new file with mode: 0644]
src/libnative/lib.rs
src/libnative/task.rs
src/librustc/back/abi.rs
src/librustc/back/link.rs
src/librustc/back/rpath.rs
src/librustc/driver/driver.rs
src/librustc/driver/session.rs
src/librustc/front/feature_gate.rs
src/librustc/front/std_inject.rs
src/librustc/front/test.rs
src/librustc/lib.rs
src/librustc/lib/llvm.rs
src/librustc/metadata/common.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/cstore.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/loader.rs
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/borrowck/doc.rs
src/librustc/middle/borrowck/gather_loans/lifetime.rs
src/librustc/middle/borrowck/gather_loans/mod.rs
src/librustc/middle/borrowck/move_data.rs
src/librustc/middle/lint.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve.rs
src/librustc/middle/trans/_match.rs
src/librustc/middle/trans/adt.rs
src/librustc/middle/trans/asm.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/build.rs
src/librustc/middle/trans/callee.rs
src/librustc/middle/trans/cleanup.rs [new file with mode: 0644]
src/librustc/middle/trans/closure.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/controlflow.rs
src/librustc/middle/trans/datum.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/trans/doc.rs [new file with mode: 0644]
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/foreign.rs
src/librustc/middle/trans/glue.rs
src/librustc/middle/trans/inline.rs
src/librustc/middle/trans/intrinsic.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/mod.rs
src/librustc/middle/trans/monomorphize.rs
src/librustc/middle/trans/reflect.rs
src/librustc/middle/trans/tvec.rs
src/librustc/middle/trans/type_.rs
src/librustc/middle/trans/type_of.rs
src/librustc/middle/trans/write_guard.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/_match.rs
src/librustc/middle/typeck/check/method.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/regionck.rs
src/librustc/middle/typeck/check/vtable.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/infer/coercion.rs
src/librustc/middle/typeck/infer/combine.rs
src/librustc/middle/typeck/variance.rs
src/librustc/util/ppaux.rs
src/librustc/util/sha2.rs
src/librustdoc/clean.rs
src/librustdoc/core.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/test.rs
src/librustpkg/lib.rs
src/librustpkg/sha1.rs
src/librustpkg/util.rs
src/libstd/ascii.rs
src/libstd/at_vec.rs
src/libstd/cleanup.rs
src/libstd/comm/mod.rs
src/libstd/comm/select.rs
src/libstd/gc.rs
src/libstd/io/extensions.rs
src/libstd/io/mem.rs
src/libstd/io/mod.rs
src/libstd/io/process.rs
src/libstd/io/signal.rs
src/libstd/io/timer.rs
src/libstd/iter.rs
src/libstd/libc.rs
src/libstd/local_data.rs
src/libstd/managed.rs
src/libstd/num/f32.rs
src/libstd/num/f64.rs
src/libstd/num/i16.rs
src/libstd/num/i32.rs
src/libstd/num/i64.rs
src/libstd/num/i8.rs
src/libstd/num/int.rs
src/libstd/num/int_macros.rs
src/libstd/num/mod.rs
src/libstd/num/u16.rs
src/libstd/num/u32.rs
src/libstd/num/u64.rs
src/libstd/num/u8.rs
src/libstd/num/uint.rs
src/libstd/num/uint_macros.rs
src/libstd/option.rs
src/libstd/path/posix.rs
src/libstd/path/windows.rs
src/libstd/prelude.rs
src/libstd/rc.rs
src/libstd/reflect.rs
src/libstd/repr.rs
src/libstd/rt/crate_map.rs
src/libstd/rt/global_heap.rs
src/libstd/rt/local_heap.rs
src/libstd/rt/task.rs
src/libstd/rt/unwind.rs
src/libstd/rt/util.rs
src/libstd/trie.rs
src/libstd/unstable/intrinsics.rs
src/libstd/unstable/lang.rs
src/libstd/unstable/raw.rs
src/libstd/vec.rs
src/libsyntax/ast.rs
src/libsyntax/ast_util.rs
src/libsyntax/codemap.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/deriving/generic.rs
src/libsyntax/ext/deriving/ty.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/format.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/registrar.rs [new file with mode: 0644]
src/libsyntax/fold.rs
src/libsyntax/lib.rs
src/libsyntax/opt_vec.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/rustllvm/RustWrapper.cpp
src/snapshots.txt
src/test/auxiliary/macro_crate_def_only.rs [new file with mode: 0644]
src/test/auxiliary/macro_crate_test.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-borrow-from-temporary.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-reborrow-from-shorter-lived-andmut.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-rvalues-mutable-bad.rs [deleted file]
src/test/compile-fail/cleanup-rvalue-scopes-cf.rs [new file with mode: 0644]
src/test/compile-fail/gated-macro_registrar.rs [new file with mode: 0644]
src/test/compile-fail/gated-phase.rs [new file with mode: 0644]
src/test/compile-fail/macro-crate-unexported-macro.rs [new file with mode: 0644]
src/test/compile-fail/macro-crate-unknown-crate.rs [new file with mode: 0644]
src/test/compile-fail/multiple-macro-registrars.rs [new file with mode: 0644]
src/test/compile-fail/phase-syntax-doesnt-resolve.rs [new file with mode: 0644]
src/test/compile-fail/removed-syntax-uniq-self.rs
src/test/debug-info/destructured-local.rs
src/test/debug-info/managed-pointer-within-unique-vec.rs
src/test/debug-info/managed-pointer-within-unique.rs
src/test/debug-info/recursive-struct.rs
src/test/run-pass/borrowck-rvalues-mutable.rs
src/test/run-pass/cleanup-arm-conditional.rs [new file with mode: 0644]
src/test/run-pass/cleanup-rvalue-for-scope.rs [new file with mode: 0644]
src/test/run-pass/cleanup-rvalue-scopes.rs [new file with mode: 0644]
src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs [new file with mode: 0644]
src/test/run-pass/cleanup-shortcircuit.rs [new file with mode: 0644]
src/test/run-pass/intrinsic-move-val.rs
src/test/run-pass/issue-10626.rs
src/test/run-pass/issue-9382.rs
src/test/run-pass/macro-crate-def-only.rs [new file with mode: 0644]
src/test/run-pass/macro-crate.rs [new file with mode: 0644]
src/test/run-pass/move-1.rs
src/test/run-pass/phase-syntax-link-does-resolve.rs [new file with mode: 0644]
src/test/run-pass/reflect-visit-data.rs
src/test/run-pass/reflect-visit-type.rs
src/test/run-pass/regions-dependent-let-ref.rs [new file with mode: 0644]
src/test/run-pass/uninit-empty-types.rs [new file with mode: 0644]

index 723496f5f384c3c07ec55688e59b234b0149f70b..5d4760136124a54b211a05c49b808acbc3a76484 100644 (file)
@@ -371,6 +371,9 @@ DRIVER_CRATE := $(S)src/driver/driver.rs
 LLVM_COMPONENTS=x86 arm mips ipo bitreader bitwriter linker asmparser jit mcjit \
                 interpreter instrumentation
 
+# Only build these LLVM tools
+LLVM_TOOLS=bugpoint llc llvm-ar llvm-as llvm-dis llvm-mc opt
+
 define DEF_LLVM_VARS
 # The configure script defines these variables with the target triples
 # separated by Z. This defines new ones with the expected format.
@@ -417,7 +420,8 @@ export CFG_ENABLE_MINGW_CROSS
 export CFG_PREFIX
 export CFG_LIBDIR
 export CFG_RUSTLIBDIR
-export LIBDIR_RELATIVE
+export CFG_LIBDIR_RELATIVE
+export CFG_DISABLE_INJECT_STD_VERSION
 
 ######################################################################
 # Subprograms
@@ -435,7 +439,7 @@ define SREQ
 # Destinations of artifacts for the host compiler
 HROOT$(1)_H_$(3) = $(3)/stage$(1)
 HBIN$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/bin
-HLIB$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/$$(LIBDIR_RELATIVE)
+HLIB$(1)_H_$(3) = $$(HROOT$(1)_H_$(3))/$$(CFG_LIBDIR_RELATIVE)
 
 # Destinations of artifacts for target architectures
 TROOT$(1)_T_$(2)_H_$(3) = $$(HLIB$(1)_H_$(3))/$$(CFG_RUSTLIBDIR)/$(2)
index 1b498bff6b229deb029ab0ed9f4a4c86ea73e98c..f758d75fe760032a47979dc242f7e754e167c7ad 100755 (executable)
--- a/configure
+++ b/configure
@@ -381,6 +381,7 @@ opt clang 0 "prefer clang to gcc for building the runtime"
 opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
 opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
 opt pax-flags 0 "apply PaX flags to rustc binaries (required for GRSecurity/PaX-patched kernels)"
+opt inject-std-version 1 "inject the current compiler version of libstd into programs"
 valopt prefix "/usr/local" "set installation prefix"
 valopt local-rust-root "/usr/local" "set prefix for local rust binary"
 valopt llvm-root "" "set LLVM root"
@@ -401,13 +402,13 @@ valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
 # On windows we just store the libraries in the bin directory because
 # there's no rpath
 # FIXME: Thise needs to parameterized over target triples. Do it in platform.mk
-LIBDIR_RELATIVE=lib
+CFG_LIBDIR_RELATIVE=lib
 if [ "$CFG_OSTYPE" = "pc-mingw32" ]
 then
-    LIBDIR_RELATIVE=bin
+    CFG_LIBDIR_RELATIVE=bin
 fi
 
-valopt libdir "${CFG_PREFIX}/${LIBDIR_RELATIVE}" "install libraries"
+valopt libdir "${CFG_PREFIX}/${CFG_LIBDIR_RELATIVE}" "install libraries"
 valopt rustlibdir "rustlib" "subdirectory name for rustc's libraries"
 
 # Validate Options
@@ -771,16 +772,16 @@ do
             make_dir $h/stage$i/bin
 
             # host lib dir
-            make_dir $h/stage$i/$LIBDIR_RELATIVE
+            make_dir $h/stage$i/$CFG_LIBDIR_RELATIVE
 
             # host test dir
             make_dir $h/stage$i/test
 
             # target bin dir
-            make_dir $h/stage$i/$LIBDIR_RELATIVE/$CFG_RUSTLIBDIR/$t/bin
+            make_dir $h/stage$i/$CFG_LIBDIR_RELATIVE/$CFG_RUSTLIBDIR/$t/bin
 
             # target lib dir
-            make_dir $h/stage$i/$LIBDIR_RELATIVE/$CFG_RUSTLIBDIR/$t/lib
+            make_dir $h/stage$i/$CFG_LIBDIR_RELATIVE/$CFG_RUSTLIBDIR/$t/lib
         done
     done
 
@@ -1037,11 +1038,12 @@ putvar CFG_TARGET
 putvar CFG_C_COMPILER
 putvar CFG_LIBDIR
 putvar CFG_RUSTLIBDIR
-putvar LIBDIR_RELATIVE
+putvar CFG_LIBDIR_RELATIVE
 putvar CFG_DISABLE_MANAGE_SUBMODULES
 putvar CFG_ANDROID_CROSS_PATH
 putvar CFG_MINGW32_CROSS_PATH
 putvar CFG_MANDIR
+putvar CFG_DISABLE_INJECT_STD_VERSION
 
 # Avoid spurious warnings from clang by feeding it original source on
 # ccache-miss rather than preprocessed input.
index 3942603159b1933190ccd537e0ad3d68748c7405..9135650c31becc5a7d7a94eedd994248ae3330a2 100644 (file)
@@ -8,6 +8,12 @@ source code.
 the Markdown docs (reference manual, tutorials, etc.) distributed with
 this git repository.
 
+[po4a](http://po4a.alioth.debian.org/) is required for generating translated
+docs from the master (English) docs.
+
+[GNU gettext](http://www.gnu.org/software/gettext/) is required for managing
+the translation data.
+
 # Building
 
 To generate all the docs, just run `make docs` from the root of the repository.
@@ -38,3 +44,43 @@ http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown
 
 A nice quick reference (for non-pandoc markdown) is at:
 http://kramdown.rubyforge.org/quickref.html
+
+# Notes for translators
+
+Notice: The procedure described below is a work in progress. We are working on
+translation system but the procedure contains some manual operations for now.
+
+To start the translation for a new language, see po4a.conf at first.
+
+To generate .pot and .po files, do something like:
+
+~~~~
+po4a --copyright-holder="The Rust Project Developers" \
+    --package-name="Rust" \
+    --package-version="0.10-pre" \
+    -M UTF-8 -L UTF-8 \
+    po4a.conf
+~~~~
+
+(the version number must be changed if it is not 0.10-pre now.)
+
+Now you can translate documents with .po files, commonly used with gettext. If
+you are not familiar with gettext-based translation, please read the online
+manual linked from http://www.gnu.org/software/gettext/ . We use UTF-8 as the
+file encoding of .po files.
+
+When you want to make a commit, do the command below before staging your
+change:
+
+~~~~
+for f in doc/po/**/*.po; do
+    msgattrib --translated $f -o $f.strip
+    if [ -e $f.strip ]; then
+       mv $f.strip $f
+    else
+       rm $f
+    fi
+done
+~~~~
+
+This removes untranslated entries from .po files to save disk space.
index cf68310d353d5ca5ffdbb83f5fb0449b553d84fa..53ad4217145aa29593984dd69c601fab298bd5a4 100644 (file)
@@ -4,52 +4,54 @@
 <style type="text/css">
 #TOC { display: none; }
 .header-section-number { display: none; }
+li {list-style-type: none; }
 </style>
 
-[The Rust tutorial](tutorial.html)  ([PDF](tutorial.pdf))  
-[The Rust reference manual](rust.html) ([PDF](rust.pdf))  
+* [The Rust tutorial](tutorial.html)  (* [PDF](tutorial.pdf))
+* [The Rust reference manual](rust.html) (* [PDF](rust.pdf))
 
 # Guides
 
-[Pointers](guide-pointers.html)  
-[References and Lifetimes](guide-lifetimes.html)  
-[Containers and Iterators](guide-container.html)  
-[Tasks and Communication](guide-tasks.html)  
-[Foreign Function Interface](guide-ffi.html)  
-[Macros](guide-macros.html)  
-[Packaging](guide-rustpkg.html)  
-[Testing](guide-testing.html)  
-[Conditions](guide-conditions.html)
-[Rust's Runtime](guide-runtime.html)
+* [Pointers](guide-pointers.html)
+* [References and Lifetimes](guide-lifetimes.html)
+* [Containers and Iterators](guide-container.html)
+* [Tasks and Communication](guide-tasks.html)
+* [Foreign Function Interface](guide-ffi.html)
+* [Macros](guide-macros.html)
+* [Packaging](guide-rustpkg.html)
+* [Testing](guide-testing.html)
+[Conditions](guide-conditions.html)
+[Rust's Runtime](guide-runtime.html)
 
 # Libraries
 
-[The standard library, `libstd`](std/index.html)  
-[The extra library, `libextra`](extra/index.html)
+* [The standard library, `libstd`](std/index.html)
+[The extra library, `libextra`](extra/index.html)
 
-[The M:N runtime library, `libgreen`](green/index.html)  
-[The 1:1 runtime library, `libnative`](native/index.html)
+* [The M:N runtime library, `libgreen`](green/index.html)
+[The 1:1 runtime library, `libnative`](native/index.html)
 
-[The Rust libuv library, `librustuv`](rustuv/index.html)  
-[The Rust packaging library, `librustpkg`](rustpkg/index.html)
+* [The Rust libuv library, `librustuv`](rustuv/index.html)
+[The Rust packaging library, `librustpkg`](rustpkg/index.html)
 
-[The Rust parser, `libsyntax`](syntax/index.html)  
-[The Rust compiler, `librustc`](rustc/index.html)
+* [The Rust parser, `libsyntax`](syntax/index.html)
+[The Rust compiler, `librustc`](rustc/index.html)
 
 # Tooling
 
-[The `rustpkg` manual](rustpkg.html)
+* [The `rustdoc` manual](rustdoc.html)
+* [The `rustpkg` manual](rustpkg.html)
 
 # FAQs
 
-[Language FAQ](complement-lang-faq.html)  
-[Project FAQ](complement-project-faq.html)  
-[Usage FAQ](complement-usage-faq.html)  
-[Code cheatsheet](complement-cheatsheet.html) - "How do I do X?"  
-[How to submit a bug report](complement-bugreport.html)
+* [Language FAQ](complement-lang-faq.html)
+* [Project FAQ](complement-project-faq.html)
+* [Usage FAQ](complement-usage-faq.html)
+[Code cheatsheet](complement-cheatsheet.html) - "How do I do X?"  
+[How to submit a bug report](complement-bugreport.html)
 
 # External resources
 
-The Rust [IRC channel](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust) - `#rust` on irc.mozilla.org  
-The Rust community on [Reddit](http://reddit.com/r/rust)  
-The Rust [wiki](http://github.com/mozilla/rust/wiki)
+The Rust [IRC channel](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust) - `#rust` on irc.mozilla.org  
+* The Rust community on [Reddit](http://reddit.com/r/rust)
+The Rust [wiki](http://github.com/mozilla/rust/wiki)
diff --git a/doc/po/ja/complement-cheatsheet.md.po b/doc/po/ja/complement-cheatsheet.md.po
new file mode 100644 (file)
index 0000000..5c13cd2
--- /dev/null
@@ -0,0 +1,152 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:13
+#, fuzzy
+#| msgid ""
+#| "~~~~ let x: f64 = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
+msgid "~~~ let x: int = 42; let y: ~str = x.to_str(); ~~~"
+msgstr ""
+"~~~~\n"
+"let x: f64 = 4.0;\n"
+"let y: uint = x as uint;\n"
+"assert!(y == 4u);\n"
+"~~~~"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:17
+#, fuzzy
+#| msgid ""
+#| "[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz [win-exe]: "
+#| "http://static.rust-lang.org/dist/rust-0.7-install.exe"
+msgid ""
+"Use [`FromStr`](http://static.rust-lang.org/doc/master/std/from_str/trait."
+"FromStr.html), and its helper function, [`from_str`](http://static.rust-lang."
+"org/doc/master/std/from_str/fn.from_str.html)."
+msgstr ""
+"[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz\n"
+"[win-exe]: http://static.rust-lang.org/dist/rust-0.7-install.exe"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:22
+#, fuzzy
+#| msgid ""
+#| "~~~~ let x: f64 = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
+msgid "~~~ let x: Option<int> = from_str(\"42\"); let y: int = x.unwrap(); ~~~"
+msgstr ""
+"~~~~\n"
+"let x: f64 = 4.0;\n"
+"let y: uint = x as uint;\n"
+"assert!(y == 4u);\n"
+"~~~~"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:29
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~ use std::num::ToStrRadix;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:33
+#, fuzzy
+#| msgid ""
+#| "~~~~ let x: f64 = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
+msgid "let x: int = 42; let y: ~str = x.to_str_radix(16); ~~~"
+msgstr ""
+"~~~~\n"
+"let x: f64 = 4.0;\n"
+"let y: uint = x as uint;\n"
+"assert!(y == 4u);\n"
+"~~~~"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:37
+#, fuzzy
+#| msgid ""
+#| "[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz [win-exe]: "
+#| "http://static.rust-lang.org/dist/rust-0.7-install.exe"
+msgid ""
+"Use [`FromStrRadix`](http://static.rust-lang.org/doc/master/std/num/trait."
+"FromStrRadix.html), and its helper function, [`from_str_radix`](http://"
+"static.rust-lang.org/doc/master/std/num/fn.from_str_radix.html)."
+msgstr ""
+"[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz\n"
+"[win-exe]: http://static.rust-lang.org/dist/rust-0.7-install.exe"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:40
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~ use std::num::from_str_radix;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:46
+#, fuzzy
+#| msgid "## Operators"
+msgid "# File operations"
+msgstr "## 演算子"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:54
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~ {.xfail-test} use std::path::Path; use std::io::fs::File;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:63
+#, fuzzy
+#| msgid ""
+#| "[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz [win-exe]: "
+#| "http://static.rust-lang.org/dist/rust-0.7-install.exe"
+msgid ""
+"Use the [`lines`](http://static.rust-lang.org/doc/master/std/io/trait.Buffer."
+"html#method.lines) method on a [`BufferedReader`](http://static.rust-lang."
+"org/doc/master/std/io/buffered/struct.BufferedReader.html)."
+msgstr ""
+"[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz\n"
+"[win-exe]: http://static.rust-lang.org/dist/rust-0.7-install.exe"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:77
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "# String operations"
+msgstr "## 他のクレートの利用"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:88 doc/guide-container.md:4
+#, fuzzy
+msgid "# Containers"
+msgstr "## 本書の表記について"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:176
+#, fuzzy
+#| msgid "[The foreign function interface][ffi]"
+msgid "# FFI (Foreign Function Interface)"
+msgstr "[他言語間インターフェース (foreign function inferface)][ffi]"
diff --git a/doc/po/ja/complement-lang-faq.md.po b/doc/po/ja/complement-lang-faq.md.po
new file mode 100644 (file)
index 0000000..a4d16a8
--- /dev/null
@@ -0,0 +1,47 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/complement-lang-faq.md:83
+#, fuzzy
+#| msgid ""
+#| "[bug-3319]: https://github.com/mozilla/rust/issues/3319 [wiki-start]: "
+#| "https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust"
+msgid ""
+"[rustc]: https://github.com/mozilla/rust/tree/master/src/librustc [resolve]: "
+"https://github.com/mozilla/rust/blob/master/src/librustc/middle/resolve.rs "
+"[borrowck]: https://github.com/mozilla/rust/blob/master/src/librustc/middle/"
+"borrowck/"
+msgstr ""
+"[bug-3319]: https://github.com/mozilla/rust/issues/3319\n"
+"[wiki-start]: https://github.com/mozilla/rust/wiki/Note-getting-started-"
+"developing-Rust"
+
+#. type: Plain text
+#: doc/complement-lang-faq.md:110
+#, fuzzy
+#| msgid ""
+#| "[bug-3319]: https://github.com/mozilla/rust/issues/3319 [wiki-start]: "
+#| "https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust"
+msgid ""
+"[unwind]: https://github.com/mozilla/rust/issues/908 [libgcc]: https://"
+"github.com/mozilla/rust/issues/1603"
+msgstr ""
+"[bug-3319]: https://github.com/mozilla/rust/issues/3319\n"
+"[wiki-start]: https://github.com/mozilla/rust/wiki/Note-getting-started-"
+"developing-Rust"
diff --git a/doc/po/ja/complement-project-faq.md.po b/doc/po/ja/complement-project-faq.md.po
new file mode 100644 (file)
index 0000000..100e1d5
--- /dev/null
@@ -0,0 +1,24 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Bullet: '* '
+#: doc/complement-project-faq.md:36
+#, fuzzy
+#| msgid "## The standard library"
+msgid "An evolving standard library."
+msgstr "## 標準ライブラリ"
diff --git a/doc/po/ja/guide-conditions.md.po b/doc/po/ja/guide-conditions.md.po
new file mode 100644 (file)
index 0000000..505d55a
--- /dev/null
@@ -0,0 +1,73 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/guide-conditions.md:2
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
+msgid "% The Rust Condition and Error-handling Guide"
+msgstr "% Rust 言語チュートリアル"
+
+#. type: Plain text
+#: doc/guide-conditions.md:4 doc/guide-ffi.md:4 doc/guide-lifetimes.md:4
+#: doc/guide-macros.md:4 doc/guide-rustpkg.md:4 doc/guide-tasks.md:4
+#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
+msgid "# Introduction"
+msgstr "# イントロダクション"
+
+#. type: Bullet: '  - '
+#: doc/guide-conditions.md:14
+#, fuzzy
+#| msgid "# Functions"
+msgid "Options"
+msgstr "# 関数"
+
+#. type: Bullet: '  - '
+#: doc/guide-conditions.md:14
+#, fuzzy
+#| msgid "## Conditionals"
+msgid "Conditions"
+msgstr "## 条件式"
+
+#. type: Plain text
+#: doc/guide-conditions.md:19
+#, fuzzy
+#| msgid "## Tuples"
+msgid "# Example program"
+msgstr "## タプル"
+
+#. type: Plain text
+#: doc/guide-conditions.md:112
+#, fuzzy
+#| msgid "# Functions"
+msgid "# Options"
+msgstr "# 関数"
+
+#. type: Plain text
+#: doc/guide-conditions.md:318
+#, fuzzy
+#| msgid "## Conditionals"
+msgid "# Conditions"
+msgstr "## 条件式"
+
+#. type: Plain text
+#: doc/guide-conditions.md:415
+#, fuzzy
+#| msgid "## Traits"
+msgid "# Trapping a condition"
+msgstr "## トレイト"
diff --git a/doc/po/ja/guide-container.md.po b/doc/po/ja/guide-container.md.po
new file mode 100644 (file)
index 0000000..6113f1f
--- /dev/null
@@ -0,0 +1,114 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/complement-cheatsheet.md:88 doc/guide-container.md:4
+#, fuzzy
+msgid "# Containers"
+msgstr "## 本書の表記について"
+
+#. type: Plain text
+#: doc/guide-container.md:2
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
+msgid "% The Rust Containers and Iterators Guide"
+msgstr "% Rust 言語チュートリアル"
+
+#. type: Plain text
+#: doc/guide-container.md:8
+#, fuzzy
+#| msgid "# Control structures"
+msgid "## Unique vectors"
+msgstr "# 制御構造"
+
+#. type: Plain text
+#: doc/guide-container.md:18
+#, fuzzy
+#| msgid "## Managed closures"
+msgid "## Maps and sets"
+msgstr "## マネージドクロージャ"
+
+#. type: Plain text
+#: doc/guide-container.md:24
+#, fuzzy
+#| msgid "## The standard library"
+msgid "The standard library provides three owned map/set types:"
+msgstr "## 標準ライブラリ"
+
+#. type: Plain text
+#: doc/guide-container.md:68
+#, fuzzy
+#| msgid "## Operators"
+msgid "# Iterators"
+msgstr "## 演算子"
+
+#. type: Plain text
+#: doc/guide-container.md:70
+#, fuzzy
+#| msgid "# Introduction"
+msgid "## Iteration protocol"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-container.md:119
+#, fuzzy
+#| msgid "# Control structures"
+msgid "## Container iterators"
+msgstr "# 制御構造"
+
+#. type: Plain text
+#: doc/guide-container.md:131
+#, fuzzy
+#| msgid "## Freezing"
+msgid "### Freezing"
+msgstr "## 凍結"
+
+#. type: Plain text
+#: doc/guide-container.md:151
+#, fuzzy
+#| msgid "## Operators"
+msgid "## Iterator adaptors"
+msgstr "## 演算子"
+
+#. type: Plain text
+#: doc/guide-container.md:201
+#, fuzzy
+#| msgid "## Loops"
+msgid "## For loops"
+msgstr "## ループ"
+
+#. type: Plain text
+#: doc/guide-container.md:257
+#, fuzzy
+#| msgid "## Conventions"
+msgid "## Conversion"
+msgstr "## 本書の表記について"
+
+#. type: Plain text
+#: doc/guide-container.md:334
+#, fuzzy
+#| msgid "# Control structures"
+msgid "## Double-ended iterators"
+msgstr "# 制御構造"
+
+#. type: Plain text
+#: doc/guide-container.md:385
+#, fuzzy
+#| msgid "# Control structures"
+msgid "## Random-access iterators"
+msgstr "# 制御構造"
diff --git a/doc/po/ja/guide-ffi.md.po b/doc/po/ja/guide-ffi.md.po
new file mode 100644 (file)
index 0000000..b61c8ef
--- /dev/null
@@ -0,0 +1,82 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/guide-conditions.md:4 doc/guide-ffi.md:4 doc/guide-lifetimes.md:4
+#: doc/guide-macros.md:4 doc/guide-rustpkg.md:4 doc/guide-tasks.md:4
+#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
+msgid "# Introduction"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-ffi.md:2
+#, fuzzy
+#| msgid "[The foreign function interface][ffi]"
+msgid "% The Rust Foreign Function Interface Guide"
+msgstr "[他言語間インターフェース (foreign function inferface)][ffi]"
+
+#. type: Plain text
+#: doc/guide-ffi.md:16
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~~ {.xfail-test} use std::libc::size_t;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/guide-ffi.md:48
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~~ {.xfail-test} use std::libc::{c_int, size_t};"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/guide-ffi.md:168 doc/tutorial.md:875
+msgid "# Destructors"
+msgstr "# デストラクタ"
+
+#. type: Plain text
+#: doc/guide-ffi.md:333
+#, fuzzy
+#| msgid "~~~~ let square = |x: int| -> uint { (x * x) as uint }; ~~~~"
+msgid "~~~~ unsafe fn kaboom(ptr: *int) -> int { *ptr } ~~~~"
+msgstr ""
+"~~~~\n"
+"let square = |x: int| -> uint { (x * x) as uint };\n"
+"~~~~~~~~\n"
+
+#. type: Plain text
+#: doc/guide-ffi.md:344
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~{.xfail-test} use std::libc;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/guide-ffi.md:363
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~{.xfail-test} use std::libc; use std::ptr;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
diff --git a/doc/po/ja/guide-lifetimes.md.po b/doc/po/ja/guide-lifetimes.md.po
new file mode 100644 (file)
index 0000000..e491afc
--- /dev/null
@@ -0,0 +1,315 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/guide-conditions.md:4 doc/guide-ffi.md:4 doc/guide-lifetimes.md:4
+#: doc/guide-macros.md:4 doc/guide-rustpkg.md:4 doc/guide-tasks.md:4
+#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
+msgid "# Introduction"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:2
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
+msgid "% The Rust References and Lifetimes Guide"
+msgstr "% Rust 言語チュートリアル"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:26
+#, fuzzy
+#| msgid "## A minimal example"
+msgid "# By example"
+msgstr "## 最小限の例"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:33
+#, fuzzy
+#| msgid "As an example, consider a simple struct type, `Point`:"
+msgid "As an example, consider a simple struct type `Point`:"
+msgstr "例として、シンプルな構造体型の `Point` について考えます。"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:41
+#, fuzzy
+#| msgid ""
+#| "We can use this simple definition to allocate points in many different "
+#| "ways. For example, in this code, each of these three local variables "
+#| "contains a point, but allocated in a different location:"
+msgid ""
+"We can use this simple definition to allocate points in many different ways. "
+"For example, in this code, each of these three local variables contains a "
+"point, but allocated in a different place:"
+msgstr ""
+"シンプルな定義ですが、この定義を使って `Point` 型のオブジェクトを様々な方法で"
+"割り当てることができます。例えば、このコードの3つのローカル変数は、それぞれ異"
+"なった場所に `Point` 型のオブジェクトを割り当てています。"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:48
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"~~~\n"
+"# struct Point {x: f64, y: f64}\n"
+"let on_the_stack :  Point =  Point {x: 3.0, y: 4.0};\n"
+"let managed_box  : @Point = @Point {x: 5.0, y: 1.0};\n"
+"let owned_box    : ~Point = ~Point {x: 7.0, y: 9.0};\n"
+"~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:60
+#, fuzzy
+#| msgid ""
+#| "Suppose we want to write a procedure that computes the distance between "
+#| "any two points, no matter where they are stored. For example, we might "
+#| "like to compute the distance between `on_the_stack` and `managed_box`, or "
+#| "between `managed_box` and `owned_box`. One option is to define a function "
+#| "that takes two arguments of type point—that is, it takes the points by "
+#| "value. But this will cause the points to be copied when we call the "
+#| "function. For points, this is probably not so bad, but often copies are "
+#| "expensive. So we’d like to define a function that takes the points by "
+#| "pointer. We can use borrowed pointers to do this:"
+msgid ""
+"Suppose we wanted to write a procedure that computed the distance between "
+"any two points, no matter where they were stored. For example, we might like "
+"to compute the distance between `on_the_stack` and `managed_box`, or between "
+"`managed_box` and `owned_box`. One option is to define a function that takes "
+"two arguments of type `Point`—that is, it takes the points by value. But if "
+"we define it this way, calling the function will cause the points to be "
+"copied. For points, this is probably not so bad, but often copies are "
+"expensive. Worse, if the data type contains mutable fields, copying can "
+"change the semantics of your program in unexpected ways. So we'd like to "
+"define a function that takes the points by pointer. We can use references to "
+"do this:"
+msgstr ""
+"`Point` 型のオブジェクトの割り当て先がどこであったとしても利用可能な、任意の "
+"2 点間の距離を計算する処理を書きたいとします。例えば、 `on_the_stack`, "
+"`managed_box` 間や `managed_box`, `owned_box` 間の距離を計算する処理です。 1"
+"つ目の実装方法として、2つの `Point` 型オブジェクトを引数にとる関数を定義する"
+"方法、すなわち、オブジェクトを値で受け渡す方法があります。しかし、この方法で"
+"は関数呼び出し時に `Point` オブジェクトのコピーが行われます。`Point` オブジェ"
+"クトの場合、このような実装はそれほど悪いものではないでしょうが、コピー処理の"
+"コストは高い場合もあります。したがって、`Point` オブジェクトをポインタ渡しす"
+"る関数を定義する必要があります。そのために、借用ポインタを利用することが可能"
+"です。"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:72 doc/tutorial.md:1394
+msgid "Now we can call `compute_distance()` in various ways:"
+msgstr ""
+"上記の `compute_distance()` 関数は、様々な方法で呼び出すことができます。"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:82
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"~~~\n"
+"# struct Point {x: f64, y: f64}\n"
+"# let on_the_stack :  Point =  Point{x: 3.0, y: 4.0};\n"
+"# let managed_box  : @Point = @Point{x: 5.0, y: 1.0};\n"
+"# let owned_box    : ~Point = ~Point{x: 7.0, y: 9.0};\n"
+"# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }\n"
+"compute_distance(&on_the_stack, managed_box);\n"
+"compute_distance(managed_box, owned_box);\n"
+"~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:89
+#, fuzzy
+#| msgid ""
+#| "Here the `&` operator is used to take the address of the variable "
+#| "`on_the_stack`; this is because `on_the_stack` has the type `Point` (that "
+#| "is, a struct value) and we have to take its address to get a value. We "
+#| "also call this _borrowing_ the local variable `on_the_stack`, because we "
+#| "are creating an alias: that is, another route to the same data."
+msgid ""
+"Here, the `&` operator takes the address of the variable `on_the_stack`; "
+"this is because `on_the_stack` has the type `Point` (that is, a struct "
+"value) and we have to take its address to get a value. We also call this "
+"_borrowing_ the local variable `on_the_stack`, because we have created an "
+"alias: that is, another name for the same data."
+msgstr ""
+"ここで `&` 演算子は `on_the_stack` 変数のアドレスを取得するために使われていま"
+"す。これは、 `on_the_stack` の型は `Point` (つまり、構造体の値) であり、呼び"
+"出した関数から値を取得させるため、構造体のアドレスを渡す必要があるからです。"
+"値の別名 (エイリアス)、すなわち、同じデータへアクセスするための別の方法を提供"
+"するので、このような操作のことをローカル変数 `on_the_stack` の __借用__ "
+"(_borrowing_) と呼びます。"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:95
+#, fuzzy
+#| msgid ""
+#| "In the case of the boxes `managed_box` and `owned_box`, however, no "
+#| "explicit action is necessary. The compiler will automatically convert a "
+#| "box like `@point` or `~point` to a borrowed pointer like `&point`. This "
+#| "is another form of borrowing; in this case, the contents of the managed/"
+#| "owned box are being lent out."
+msgid ""
+"In contrast, we can pass the boxes `managed_box` and `owned_box` to "
+"`compute_distance` directly. The compiler automatically converts a box like "
+"`@Point` or `~Point` to a reference like `&Point`. This is another form of "
+"borrowing: in this case, the caller lends the contents of the managed or "
+"owned box to the callee."
+msgstr ""
+"ボックスである `managed_box` と `owned_box` の場合は、特に明示的な操作を行う"
+"必要はありません。コンパイラは `@point` や `~point` のようなボックスを自動的"
+"に `&point` のような借用ポインタへと変換します。これは、別の形態の借用 "
+"(borrowing) です。この場合、マネージド/所有ボックスの内容が貸し出されていま"
+"す。"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:105
+#, fuzzy
+#| msgid ""
+#| "Whenever a value is borrowed, there are some limitations on what you can "
+#| "do with the original. For example, if the contents of a variable have "
+#| "been lent out, you cannot send that variable to another task, nor will "
+#| "you be permitted to take actions that might cause the borrowed value to "
+#| "be freed or to change its type. This rule should make intuitive sense: "
+#| "you must wait for a borrowed value to be returned (that is, for the "
+#| "borrowed pointer to go out of scope) before you can make full use of it "
+#| "again."
+msgid ""
+"Whenever a caller lends data to a callee, there are some limitations on what "
+"the caller can do with the original. For example, if the contents of a "
+"variable have been lent out, you cannot send that variable to another task. "
+"In addition, the compiler will reject any code that might cause the borrowed "
+"value to be freed or overwrite its component fields with values of different "
+"types (I'll get into what kinds of actions those are shortly). This rule "
+"should make intuitive sense: you must wait for a borrower to return the "
+"value that you lent it (that is, wait for the reference to go out of scope)  "
+"before you can make full use of it again."
+msgstr ""
+"値が借用されている間、借用元の値に対して行える操作がいくらか制限されます。例"
+"えば、変数の内容が貸し出された場合、その変数を他のタスクに送信することはでき"
+"ませんし、借用された値を解放したり、型が変化させるような操作も行うことができ"
+"ません。このルールは理にかなったものでしょう。貸し出した値を最大限に活用する "
+"(make full use of it) ためには、貸し出した値の返却 (借用ポインタが存在するス"
+"コープを抜ける) を待たなければなりません。"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:114
+#, fuzzy
+#| msgid ""
+#| "~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: "
+#| "20f }; println(fmt!(\"%f\", point.x)); ~~~"
+msgid ""
+"~~~ # struct Point {x: f64, y: f64} let on_the_stack: Point = Point {x: 3.0, "
+"y: 4.0}; ~~~"
+msgstr ""
+"~~~\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let point = &@~Point { x: 10f, y: 20f };\n"
+"println(fmt!(\"%f\", point.x));\n"
+"~~~"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:124
+#, fuzzy
+#| msgid ""
+#| "~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: "
+#| "20f }; println(fmt!(\"%f\", point.x)); ~~~"
+msgid ""
+"~~~ # struct Point {x: f64, y: f64} let on_the_stack2: &Point = &Point {x: "
+"3.0, y: 4.0}; ~~~"
+msgstr ""
+"~~~\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let point = &@~Point { x: 10f, y: 20f };\n"
+"println(fmt!(\"%f\", point.x));\n"
+"~~~"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:134
+#, fuzzy
+#| msgid ""
+#| "~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: "
+#| "20f }; println(fmt!(\"%f\", point.x)); ~~~"
+msgid ""
+"~~~ # struct Point {x: f64, y: f64} let tmp = Point {x: 3.0, y: 4.0}; let "
+"on_the_stack2 : &Point = &tmp; ~~~"
+msgstr ""
+"~~~\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let point = &@~Point { x: 10f, y: 20f };\n"
+"println(fmt!(\"%f\", point.x));\n"
+"~~~"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:180
+#, fuzzy
+#| msgid "# Borrowed pointers"
+msgid "# Borrowing managed boxes and rooting"
+msgstr "# 借用ポインタ"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:262
+#, fuzzy
+#| msgid "# Borrowed pointers"
+msgid "# Borrowing owned boxes"
+msgstr "# 借用ポインタ"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:367
+#, fuzzy
+#| msgid "# Borrowed pointers"
+msgid "# Borrowing and enums"
+msgstr "# 借用ポインタ"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:477
+#, fuzzy
+#| msgid "# Dereferencing pointers"
+msgid "# Returning references"
+msgstr "# ポインタのデリファレンス"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:490
+#, fuzzy
+#| msgid ""
+#| "~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: "
+#| "20f }; println(fmt!(\"%f\", point.x)); ~~~"
+msgid ""
+"~~~ struct Point {x: f64, y: f64} fn get_x<'r>(p: &'r Point) -> &'r f64 { &p."
+"x } ~~~"
+msgstr ""
+"~~~\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let point = &@~Point { x: 10f, y: 20f };\n"
+"println(fmt!(\"%f\", point.x));\n"
+"~~~"
+
+#. type: Plain text
+#: doc/guide-lifetimes.md:659
+#, fuzzy
+#| msgid "## Conventions"
+msgid "# Conclusion"
+msgstr "## 本書の表記について"
diff --git a/doc/po/ja/guide-macros.md.po b/doc/po/ja/guide-macros.md.po
new file mode 100644 (file)
index 0000000..41ba4b0
--- /dev/null
@@ -0,0 +1,94 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/guide-conditions.md:4 doc/guide-ffi.md:4 doc/guide-lifetimes.md:4
+#: doc/guide-macros.md:4 doc/guide-rustpkg.md:4 doc/guide-tasks.md:4
+#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
+msgid "# Introduction"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-macros.md:2
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
+msgid "% The Rust Macros Guide"
+msgstr "% Rust 言語チュートリアル"
+
+#. type: Plain text
+#: doc/guide-macros.md:67
+#, fuzzy
+#| msgid "## Do syntax"
+msgid "# Invocation syntax"
+msgstr "## do 構文"
+
+#. type: Plain text
+#: doc/guide-macros.md:100
+#, fuzzy
+#| msgid "# Introduction"
+msgid "## Invocation location"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-macros.md:115
+#, fuzzy
+#| msgid "## Traits"
+msgid "# Transcription syntax"
+msgstr "## トレイト"
+
+#. type: Plain text
+#: doc/guide-macros.md:135
+#, fuzzy
+#| msgid "# Introduction"
+msgid "## Interpolation location"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-macros.md:143
+#, fuzzy
+#| msgid "# Introduction"
+msgid "## Invocation"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-macros.md:181
+#, fuzzy
+#| msgid "## Traits"
+msgid "### Transcription"
+msgstr "## トレイト"
+
+#. type: Plain text
+#: doc/guide-macros.md:193
+#, fuzzy
+#| msgid "## Pattern matching"
+msgid "## Parsing limitations"
+msgstr "## パターンマッチ"
+
+#. type: Plain text
+#: doc/guide-macros.md:212
+#, fuzzy
+#| msgid "## Pattern matching"
+msgid "# Macro argument pattern matching"
+msgstr "## パターンマッチ"
+
+#. type: Plain text
+#: doc/guide-macros.md:214
+#, fuzzy
+#| msgid "## Conventions"
+msgid "## Motivation"
+msgstr "## 本書の表記について"
diff --git a/doc/po/ja/guide-pointers.md.po b/doc/po/ja/guide-pointers.md.po
new file mode 100644 (file)
index 0000000..bd23e1a
--- /dev/null
@@ -0,0 +1,292 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/guide-pointers.md:2
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
+msgid "% The Rust Pointer Guide"
+msgstr "% Rust 言語チュートリアル"
+
+#. type: Plain text
+#: doc/guide-pointers.md:21
+#, fuzzy
+#| msgid "~~~~ let square = |x: int| -> uint { (x * x) as uint }; ~~~~"
+msgid "~~~rust fn succ(x: &int) -> int { *x + 1 } ~~~"
+msgstr ""
+"~~~~\n"
+"let square = |x: int| -> uint { (x * x) as uint };\n"
+"~~~~~~~~\n"
+
+#. type: Plain text
+#: doc/guide-pointers.md:58
+#, fuzzy
+#| msgid "~~~~ let square = |x: int| -> uint { (x * x) as uint }; ~~~~"
+msgid "~~~rust fn succ(x: int) -> int { x + 1 }"
+msgstr ""
+"~~~~\n"
+"let square = |x: int| -> uint { (x * x) as uint };\n"
+"~~~~~~~~\n"
+
+#. type: Plain text
+#: doc/guide-pointers.md:115
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"fn main() {\n"
+"    let p0 = Point { x: 5, y: 10};\n"
+"    let p1 = transform(p0);\n"
+"    println!(\"{:?}\", p1);\n"
+"}\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-pointers.md:129
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"~~~rust\n"
+"# struct Point {\n"
+"#     x: int,\n"
+"#     y: int,\n"
+"# }\n"
+"# let p0 = Point { x: 5, y: 10};\n"
+"fn transform(p: &Point) -> Point {\n"
+"    Point { x: p.x + 1, y: p.y + 1}\n"
+"}\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-pointers.md:145
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"fn transform(p: Point) -> Point {\n"
+"    Point { x: p.x + 1, y: p.y + 1}\n"
+"}\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-pointers.md:152
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"fn main() {\n"
+"    let p0 = Point { x: 5, y: 10};\n"
+"    let p1 = transform(p0);\n"
+"    println!(\"{:?}\", p1);\n"
+"}\n"
+"~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-pointers.md:162
+#, fuzzy
+#| msgid "# Borrowed pointers"
+msgid "# Owned Pointers"
+msgstr "# 借用ポインタ"
+
+#. type: Plain text
+#: doc/guide-pointers.md:175
+#, fuzzy
+msgid "## References to Traits"
+msgstr "# ポインタのデリファレンス"
+
+#. type: Plain text
+#: doc/guide-pointers.md:181
+#, fuzzy
+#| msgid "# Data structures"
+msgid "## Recursive Data Structures"
+msgstr "# データ構造"
+
+#. type: Plain text
+#: doc/guide-pointers.md:229
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"fn main() {\n"
+"    let a = Point { x: 10, y: 20 };\n"
+"    do spawn {\n"
+"        println!(\"{}\", a.x);\n"
+"    }\n"
+"}\n"
+"~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-pointers.md:246
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"fn main() {\n"
+"    let a = ~Point { x: 10, y: 20 };\n"
+"    do spawn {\n"
+"        println!(\"{}\", a.x);\n"
+"    }\n"
+"}\n"
+"~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-pointers.md:251
+#, fuzzy
+#| msgid "## Managed boxes"
+msgid "# Managed Pointers"
+msgstr "## マネージドボックス"
+
+#. type: Plain text
+#: doc/guide-pointers.md:277
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"fn main() {\n"
+"    let a = ~Point { x: 10, y: 20 };\n"
+"    let b = a;\n"
+"    println!(\"{}\", b.x);\n"
+"    println!(\"{}\", a.x);\n"
+"}\n"
+"~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-pointers.md:308
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"fn main() {\n"
+"    let a = @Point { x: 10, y: 20 };\n"
+"    let b = a;\n"
+"    println!(\"{}\", b.x);\n"
+"    println!(\"{}\", a.x);\n"
+"}\n"
+"~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-pointers.md:326 doc/tutorial.md:1345
+#, fuzzy
+msgid "# References"
+msgstr "# ポインタのデリファレンス"
+
+#. type: Plain text
+#: doc/guide-pointers.md:336
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~rust use std::num::sqrt;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/guide-pointers.md:352
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+msgid ""
+"fn main() {\n"
+"    let origin = @Point { x: 0.0, y: 0.0 };\n"
+"    let p1     = ~Point { x: 5.0, y: 3.0 };\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
+
+#. type: Plain text
+#: doc/guide-pointers.md:378
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
+msgid ""
+"~~~rust{.xfail-test}\n"
+"fn main() {\n"
+"    println!(\"{}\", x);\n"
+"    let x = 5;\n"
+"}\n"
+"~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
+
+#. type: Plain text
+#: doc/guide-pointers.md:433
+#, fuzzy
+#| msgid "# Dereferencing pointers"
+msgid "# Returning Pointers"
+msgstr "# ポインタのデリファレンス"
+
+#. type: Plain text
+#: doc/guide-pointers.md:444
+#, fuzzy, no-wrap
+#| msgid "~~~~ let square = |x: int| -> uint { (x * x) as uint }; ~~~~"
+msgid ""
+"~~~rust\n"
+"fn foo(x: ~int) -> ~int {\n"
+"    return ~*x;\n"
+"}\n"
+msgstr ""
+"~~~~\n"
+"let square = |x: int| -> uint { (x * x) as uint };\n"
+"~~~~~~~~\n"
+
+#. type: Plain text
+#: doc/guide-pointers.md:457 doc/guide-pointers.md:471
+#, fuzzy, no-wrap
+#| msgid "~~~~ let square = |x: int| -> uint { (x * x) as uint }; ~~~~"
+msgid ""
+"~~~rust\n"
+"fn foo(x: ~int) -> int {\n"
+"    return *x;\n"
+"}\n"
+msgstr ""
+"~~~~\n"
+"let square = |x: int| -> uint { (x * x) as uint };\n"
+"~~~~~~~~\n"
diff --git a/doc/po/ja/guide-rustpkg.md.po b/doc/po/ja/guide-rustpkg.md.po
new file mode 100644 (file)
index 0000000..d8d2b80
--- /dev/null
@@ -0,0 +1,112 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/guide-conditions.md:4 doc/guide-ffi.md:4 doc/guide-lifetimes.md:4
+#: doc/guide-macros.md:4 doc/guide-rustpkg.md:4 doc/guide-tasks.md:4
+#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
+msgid "# Introduction"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:2
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
+msgid "% The Rust Packaging Guide"
+msgstr "% Rust 言語チュートリアル"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:11
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "# Installing External Packages"
+msgstr "## 他のクレートの利用"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:22
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
+msgid ""
+"fn main() {\n"
+"    hello::world();\n"
+"}\n"
+"~~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:91
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "# Building your own Package"
+msgstr "## 他のクレートの利用"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:98
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "## Creating our workspace"
+msgstr "## 他のクレートの利用"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:115
+#, fuzzy
+#| msgid "# Introduction"
+msgid "## Installation"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:149
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
+msgid ""
+"pub fn world() {\n"
+"    println!(\"Hello, world.\");\n"
+"}\n"
+"~~~\n"
+msgstr ""
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:161
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "## Building your package"
+msgstr "## 他のクレートの利用"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:209
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "# Testing your Package"
+msgstr "## 他のクレートの利用"
+
+#. type: Plain text
+#: doc/guide-rustpkg.md:257
+#, fuzzy
+#| msgid "## Managed boxes"
+msgid "# More resources"
+msgstr "## マネージドボックス"
diff --git a/doc/po/ja/guide-tasks.md.po b/doc/po/ja/guide-tasks.md.po
new file mode 100644 (file)
index 0000000..a86a204
--- /dev/null
@@ -0,0 +1,81 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/guide-conditions.md:4 doc/guide-ffi.md:4 doc/guide-lifetimes.md:4
+#: doc/guide-macros.md:4 doc/guide-rustpkg.md:4 doc/guide-tasks.md:4
+#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
+msgid "# Introduction"
+msgstr "# イントロダクション"
+
+#. type: Plain text
+#: doc/guide-tasks.md:2
+#, fuzzy
+#| msgid "[Tasks and communication][tasks]"
+msgid "% The Rust Tasks and Communication Guide"
+msgstr "[タスクと通信][tasks]"
+
+#. type: Plain text
+#: doc/guide-tasks.md:64
+#, fuzzy
+#| msgid "# Syntax basics"
+msgid "# Basics"
+msgstr "# 基本的な構文"
+
+#. type: Plain text
+#: doc/guide-tasks.md:73 doc/guide-tasks.md:132
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~~ # use std::task::spawn;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/guide-tasks.md:113
+#, fuzzy
+#| msgid "## Conditionals"
+msgid "## Communication"
+msgstr "## 条件式"
+
+#. type: Plain text
+#: doc/guide-tasks.md:214
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~ # use std::task::spawn;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/guide-tasks.md:246
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~ # use std::task::spawn; # use std::vec;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/guide-tasks.md:327
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~ # use std::vec; # use std::rand; use extra::arc::Arc;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
diff --git a/doc/po/ja/guide-testing.md.po b/doc/po/ja/guide-testing.md.po
new file mode 100644 (file)
index 0000000..b42d0fe
--- /dev/null
@@ -0,0 +1,75 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/guide-testing.md:2
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
+msgid "% The Rust Testing Guide"
+msgstr "% Rust 言語チュートリアル"
+
+#. type: Plain text
+#: doc/guide-testing.md:4
+#, fuzzy
+#| msgid "# Getting started"
+msgid "# Quick start"
+msgstr "# はじめに"
+
+#. type: Plain text
+#: doc/guide-testing.md:127 doc/tutorial.md:776
+#, fuzzy
+#| msgid "## A minimal example"
+msgid "For example:"
+msgstr "## 最小限の例"
+
+#. type: Plain text
+#: doc/guide-testing.md:131
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~ extern mod extra; use std::vec;"
+msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
+
+#. type: Plain text
+#: doc/guide-testing.md:167
+#, fuzzy
+#| msgid "## Tuples"
+msgid "## Examples"
+msgstr "## タプル"
+
+#. type: Plain text
+#: doc/guide-testing.md:169
+#, fuzzy
+#| msgid "## Tuple structs"
+msgid "### Typical test run"
+msgstr "## タプル構造体"
+
+#. type: Plain text
+#: doc/guide-testing.md:197
+#, fuzzy
+#| msgid "# Dereferencing pointers"
+msgid "### Running ignored tests"
+msgstr "# ポインタのデリファレンス"
+
+#. type: Plain text
+#: doc/guide-testing.md:235
+#, fuzzy
+#| msgid "## Declaring and implementing traits"
+msgid "## Saving and ratcheting metrics"
+msgstr "## トレイトの宣言と実装"
diff --git a/doc/po/ja/index.md.po b/doc/po/ja/index.md.po
new file mode 100644 (file)
index 0000000..2941d50
--- /dev/null
@@ -0,0 +1,31 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-14 21:02+0900\n"
+"PO-Revision-Date: 2014-01-14 21:02+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/index.md:2
+#, fuzzy
+#| msgid "## Using the rust tool"
+msgid "% Rust documentation"
+msgstr "## `rust` コマンドを利用する"
+
+#. type: Plain text
+#: doc/index.md:26
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "# Libraries"
+msgstr "## 他のクレートの利用"
index 99392964e7aadde9d6d6cf6adec5ce5c98db3068..d3567449e0e9eb3f4fe953e2a4d0c25e9edb381e 100644 (file)
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: Rust 0.8\n"
-"POT-Creation-Date: 2013-08-12 02:06+0900\n"
+"POT-Creation-Date: 2014-01-14 21:02+0900\n"
 "PO-Revision-Date: 2013-08-05 19:40+0900\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -17,6487 +17,1012 @@ msgstr ""
 "Plural-Forms: nplurals=1; plural=0;\n"
 
 #. type: Plain text
-#: doc/rust.md:2
-msgid "% Rust Reference Manual"
-msgstr ""
-
-#. type: Plain text
+#: doc/guide-conditions.md:4 doc/guide-ffi.md:4 doc/guide-lifetimes.md:4
+#: doc/guide-macros.md:4 doc/guide-rustpkg.md:4 doc/guide-tasks.md:4
 #: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
-#: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
-#: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
 msgid "# Introduction"
 msgstr "# イントロダクション"
 
 #. type: Plain text
-#: doc/rust.md:7
-msgid ""
-"This document is the reference manual for the Rust programming language. It "
-"provides three kinds of material:"
-msgstr ""
+#: doc/rust.md:2
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
+msgid "% The Rust Reference Manual"
+msgstr "% Rust 言語チュートリアル"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:15
-msgid ""
-"Chapters that formally define the language grammar and, for each construct, "
-"informally describe its semantics and give examples of its use."
-msgstr ""
+#. type: Plain text
+#: doc/rust.md:54
+#, fuzzy
+#| msgid "## Conventions"
+msgid "# Notation"
+msgstr "## 本書の表記について"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:15
-msgid ""
-"Chapters that informally describe the memory model, concurrency model, "
-"runtime services, linkage model and debugging facilities."
-msgstr ""
+#. type: Plain text
+#: doc/rust.md:91
+#, fuzzy
+#| msgid "# Introduction"
+msgid "## Unicode productions"
+msgstr "# イントロダクション"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:15
-msgid ""
-"Appendix chapters providing rationale and references to languages that "
-"influenced the design."
-msgstr ""
+#. type: Plain text
+#: doc/rust.md:98
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "## String table productions"
+msgstr "## 他のクレートの利用"
 
 #. type: Plain text
-#: doc/rust.md:19
-msgid ""
-"This document does not serve as a tutorial introduction to the language. "
-"Background familiarity with the language is assumed. A separate [tutorial] "
-"document is available to help acquire such background familiarity."
-msgstr ""
+#: doc/rust.md:113
+#, fuzzy
+#| msgid "# Data structures"
+msgid "# Lexical structure"
+msgstr "# データ構造"
 
 #. type: Plain text
-#: doc/rust.md:24
-msgid ""
-"This document also does not serve as a reference to the [standard] or "
-"[extra] libraries included in the language distribution. Those libraries are "
-"documented separately by extracting documentation attributes from their "
-"source code."
-msgstr ""
+#: doc/rust.md:152
+#, fuzzy
+#| msgid "## Conventions"
+msgid "## Comments"
+msgstr "## 本書の表記について"
 
 #. type: Plain text
-#: doc/rust.md:28
-msgid ""
-"[tutorial]: tutorial.html [standard]: std/index.html [extra]: extra/index."
-"html"
-msgstr ""
+#: doc/rust.md:190
+#, fuzzy
+#| msgid "## Tuples"
+msgid "## Tokens"
+msgstr "## タプル"
 
 #. type: Plain text
-#: doc/rust.md:30 doc/rustpkg.md:8
-msgid "## Disclaimer"
-msgstr ""
+#: doc/rust.md:226
+#, fuzzy
+#| msgid "## Operators"
+msgid "### Literals"
+msgstr "## 演算子"
 
 #. type: Plain text
-#: doc/rust.md:34
-msgid ""
-"Rust is a work in progress. The language continues to evolve as the design "
-"shifts and is fleshed out in working code. Certain parts work, certain parts "
-"do not, certain parts will be removed or changed."
-msgstr ""
+#: doc/rust.md:238
+#, fuzzy
+#| msgid "# Vectors and strings"
+msgid "#### Character and string literals"
+msgstr "# ベクタと文字列"
 
 #. type: Plain text
-#: doc/rust.md:39
-msgid ""
-"This manual is a snapshot written in the present tense. All features "
-"described exist in working code unless otherwise noted, but some are quite "
-"primitive or remain to be further modified by planned work. Some may be "
-"temporary. It is a *draft*, and we ask that you not take anything you read "
-"here as final."
-msgstr ""
+#: doc/rust.md:345
+#, fuzzy
+#| msgid "# Control structures"
+msgid "##### Integer literals"
+msgstr "# 制御構造"
 
 #. type: Plain text
-#: doc/rust.md:43
-msgid ""
-"If you have suggestions to make, please try to focus them on *reductions* to "
-"the language: possible features that can be combined or omitted. We aim to "
-"keep the size and complexity of the language under control."
+#: doc/rust.md:459
+#, fuzzy
+#| msgid "~~~~ {.ignore} let foo = 10;"
+msgid "~~~~ {.ignore} x; x::y::z; ~~~~"
 msgstr ""
+"~~~~ {.ignore}\n"
+"let foo = 10;"
 
 #. type: Plain text
-#: doc/rust.md:52
-msgid ""
-"> **Note:** The grammar for Rust given in this document is rough and > very "
-"incomplete; only a modest number of sections have accompanying grammar > "
-"rules. Formalizing the grammar accepted by the Rust parser is ongoing work, "
-"> but future versions of this document will contain a complete > grammar. "
-"Moreover, we hope that this grammar will be extracted and verified > as "
-"LL(1) by an automated grammar-analysis tool, and further tested against the "
-"> Rust sources. Preliminary versions of this automation exist, but are not "
-"yet > complete."
-msgstr ""
+#: doc/rust.md:479
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "# Syntax extensions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:54
-msgid "# Notation"
-msgstr ""
+#: doc/rust.md:524
+#, fuzzy
+#| msgid "## A minimal example"
+msgid "### Macro By Example"
+msgstr "## 最小限の例"
 
 #. type: Plain text
-#: doc/rust.md:62
-msgid ""
-"Rust's grammar is defined over Unicode codepoints, each conventionally "
-"denoted `U+XXXX`, for 4 or more hexadecimal digits `X`. _Most_ of Rust's "
-"grammar is confined to the ASCII range of Unicode, and is described in this "
-"document by a dialect of Extended Backus-Naur Form (EBNF), specifically a "
-"dialect of EBNF supported by common automated LL(k) parsing tools such as "
-"`llgen`, rather than the dialect given in ISO 14977. The dialect can be "
-"defined self-referentially as follows:"
-msgstr ""
+#: doc/rust.md:560
+#, fuzzy
+#| msgid "## Pattern matching"
+msgid "### Parsing limitations"
+msgstr "## パターンマッチ"
 
 #. type: Plain text
-#: doc/rust.md:64
-msgid "~~~~~~~~ {.ebnf .notation}"
-msgstr ""
+#: doc/rust.md:579
+#, fuzzy
+#| msgid "# Modules and crates"
+msgid "# Crates and source files"
+msgstr "# モジュールとクレート"
 
 #. type: Plain text
-#: doc/rust.md:72
-#, no-wrap
-msgid ""
-"grammar : rule + ;\n"
-"rule    : nonterminal ':' productionrule ';' ;\n"
-"productionrule : production [ '|' production ] * ;\n"
-"production : term * ;\n"
-"term : element repeats ;\n"
-"element : LITERAL | IDENTIFIER | '[' productionrule ']' ;\n"
-"repeats : [ '*' | '+' ] NUMBER ? | NUMBER ? | '?' ;\n"
+#: doc/rust.md:626
+#, fuzzy
+#| msgid "// Turn on a warning #[warn(non_camel_case_types)]"
+msgid "// Turn on a warning #[ warn(non_camel_case_types) ]; ~~~~"
 msgstr ""
+"// 警告を有効にする\n"
+"#[warn(non_camel_case_types)]"
 
 #. type: Plain text
-#: doc/rust.md:74 doc/rust.md:416 doc/rust.md:486
-msgid "~~~~~~~~"
-msgstr ""
+#: doc/rust.md:631
+#, fuzzy
+#| msgid "# Vectors and strings"
+msgid "# Items and attributes"
+msgstr "# ベクタと文字列"
 
 #. type: Plain text
-#: doc/rust.md:76
-msgid "Where:"
-msgstr ""
+#: doc/rust.md:636
+#, fuzzy
+#| msgid "## Operators"
+msgid "## Items"
+msgstr "## 演算子"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:89
-msgid "Whitespace in the grammar is ignored."
-msgstr ""
+#. type: Plain text
+#: doc/rust.md:765
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "##### Extern mod declarations"
+msgstr "## 他のクレートの利用"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:89
-msgid "Square brackets are used to group rules."
+#. type: Plain text
+#: doc/rust.md:788
+#, fuzzy
+#| msgid "~~~~ {.ignore} let foo = 10;"
+msgid "~~~~ {.xfail-test} extern mod pcre;"
 msgstr ""
+"~~~~ {.ignore}\n"
+"let foo = 10;"
 
 #. type: Plain text
-#: doc/rust.md:89
-#, no-wrap
-msgid ""
-"  - `LITERAL` is a single printable ASCII character, or an escaped hexadecimal\n"
-"     ASCII code of the form `\\xQQ`, in single quotes, denoting the corresponding\n"
-"     Unicode codepoint `U+00QQ`.\n"
-"  - `IDENTIFIER` is a nonempty string of ASCII letters and underscores.\n"
-"  - The `repeat` forms apply to the adjacent `element`, and are as follows:\n"
-"    - `?` means zero or one repetition\n"
-"    - `*` means zero or more repetitions\n"
-"    - `+` means one or more repetitions\n"
-"    - NUMBER trailing a repeat symbol gives a maximum repetition count\n"
-"    - NUMBER on its own gives an exact repetition count\n"
-msgstr ""
+#: doc/rust.md:797
+#, fuzzy
+#| msgid "## Conventions"
+msgid "##### Use declarations"
+msgstr "## 本書の表記について"
 
 #. type: Plain text
-#: doc/rust.md:91
-msgid "This EBNF dialect should hopefully be familiar to many readers."
+#: doc/rust.md:827
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~~ use std::num::sin; use std::option::{Some, None};"
 msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
 
 #. type: Plain text
-#: doc/rust.md:93
-msgid "## Unicode productions"
-msgstr ""
+#: doc/rust.md:900
+#, fuzzy
+#| msgid "# Functions"
+msgid "### Functions"
+msgstr "# 関数"
 
 #. type: Plain text
-#: doc/rust.md:98
-msgid ""
-"A few productions in Rust's grammar permit Unicode codepoints outside the "
-"ASCII range.  We define these productions in terms of character properties "
-"specified in the Unicode standard, rather than in terms of ASCII-range "
-"codepoints.  The section [Special Unicode Productions](#special-unicode-"
-"productions) lists these productions."
+#: doc/rust.md:930
+#, fuzzy
+#| msgid "~~~ fn first((value, _): (int, f64)) -> int { value } ~~~"
+msgid "~~~~ fn first((value, _): (int, int)) -> int { value } ~~~~"
 msgstr ""
+"~~~\n"
+"fn first((value, _): (int, f64)) -> int { value }\n"
+"~~~"
 
 #. type: Plain text
-#: doc/rust.md:100
-msgid "## String table productions"
-msgstr ""
+#: doc/rust.md:933
+#, fuzzy
+#| msgid "## Conventions"
+msgid "#### Generic functions"
+msgstr "## 本書の表記について"
 
 #. type: Plain text
-#: doc/rust.md:109
-msgid ""
-"Some rules in the grammar -- notably [unary operators](#unary-operator-"
-"expressions), [binary operators](#binary-operator-expressions), and "
-"[keywords](#keywords) -- are given in a simplified form: as a listing of a "
-"table of unquoted, printable whitespace-separated strings. These cases form "
-"a subset of the rules regarding the [token](#tokens) rule, and are assumed "
-"to be the result of a lexical-analysis phase feeding the parser, driven by a "
-"DFA, operating over the disjunction of all such string table entries."
+#: doc/rust.md:971
+#, fuzzy
+#| msgid "~~~~ let square = |x: int| -> uint { (x * x) as uint }; ~~~~"
+msgid "~~~~ fn id<T>(x: T) -> T { x } ~~~~"
 msgstr ""
+"~~~~\n"
+"let square = |x: int| -> uint { (x * x) as uint };\n"
+"~~~~~~~~\n"
 
 #. type: Plain text
-#: doc/rust.md:113
-msgid ""
-"When such a string enclosed in double-quotes (`\"`) occurs inside the "
-"grammar, it is an implicit reference to a single member of such a string "
-"table production. See [tokens](#tokens) for more information."
-msgstr ""
+#: doc/rust.md:978
+#, fuzzy
+#| msgid "## Conventions"
+msgid "#### Unsafety"
+msgstr "## 本書の表記について"
+
+#. type: Bullet: '  - '
+#: doc/rust.md:985
+#, fuzzy
+#| msgid "# Dereferencing pointers"
+msgid "Dereferencing a [raw pointer](#pointer-types)."
+msgstr "# ポインタのデリファレンス"
 
 #. type: Plain text
-#: doc/rust.md:116
-msgid "# Lexical structure"
-msgstr ""
+#: doc/rust.md:987
+#, fuzzy
+#| msgid "## Conventions"
+msgid "##### Unsafe functions"
+msgstr "## 本書の表記について"
 
 #. type: Plain text
-#: doc/rust.md:118
-msgid "## Input format"
-msgstr ""
+#: doc/rust.md:992
+#, fuzzy
+#| msgid "## Conventions"
+msgid "##### Unsafe blocks"
+msgstr "## 本書の表記について"
+
+#. type: Bullet: '* '
+#: doc/rust.md:1034
+#, fuzzy
+#| msgid "# Data structures"
+msgid "Data races"
+msgstr "# データ構造"
+
+#. type: Bullet: '* '
+#: doc/rust.md:1034
+#, fuzzy
+#| msgid "# Dereferencing pointers"
+msgid "Dereferencing a null/dangling raw pointer"
+msgstr "# ポインタのデリファレンス"
 
 #. type: Plain text
-#: doc/rust.md:124
-msgid ""
-"Rust input is interpreted as a sequence of Unicode codepoints encoded in "
-"UTF-8, normalized to Unicode normalization form NFKC.  Most Rust grammar "
-"rules are defined in terms of printable ASCII-range codepoints, but a small "
-"number are defined in terms of Unicode properties or explicit codepoint "
-"lists.  ^[Substitute definitions for the special Unicode productions are "
-"provided to the grammar verifier, restricted to ASCII range, when verifying "
-"the grammar in this document.]"
-msgstr ""
+#: doc/rust.md:1049
+#, fuzzy
+#| msgid "## Conventions"
+msgid "#### Diverging functions"
+msgstr "## 本書の表記について"
 
 #. type: Plain text
-#: doc/rust.md:126
-msgid "## Special Unicode Productions"
-msgstr ""
+#: doc/rust.md:1096
+#, fuzzy
+#| msgid "## Conventions"
+msgid "#### Extern functions"
+msgstr "## 本書の表記について"
 
 #. type: Plain text
-#: doc/rust.md:129
-msgid ""
-"The following productions in the Rust grammar are defined in terms of "
-"Unicode properties: `ident`, `non_null`, `non_star`, `non_eol`, "
-"`non_slash_or_star`, `non_single_quote` and `non_double_quote`."
-msgstr ""
+#: doc/rust.md:1125
+#, fuzzy
+#| msgid "## Conventions"
+msgid "### Type definitions"
+msgstr "## 本書の表記について"
 
 #. type: Plain text
-#: doc/rust.md:131
-msgid "### Identifiers"
-msgstr ""
+#: doc/rust.md:1140
+#, fuzzy
+#| msgid "## Structs"
+msgid "### Structures"
+msgstr "## 構造体"
 
 #. type: Plain text
-#: doc/rust.md:133
+#: doc/rust.md:1150
+#, fuzzy
+#| msgid ""
+#| "~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: "
+#| "20f }; println(fmt!(\"%f\", point.x)); ~~~"
 msgid ""
-"The `ident` production is any nonempty Unicode string of the following form:"
+"~~~~ struct Point {x: int, y: int} let p = Point {x: 10, y: 11}; let px: int "
+"= p.x; ~~~~"
 msgstr ""
+"~~~\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let point = &@~Point { x: 10f, y: 20f };\n"
+"println(fmt!(\"%f\", point.x));\n"
+"~~~"
 
-#. type: Bullet: '   - '
-#: doc/rust.md:136
-msgid "The first character has property `XID_start`"
-msgstr ""
+#. type: Plain text
+#: doc/rust.md:1170
+#, fuzzy
+#| msgid "## Enums"
+msgid "### Enumerations"
+msgstr "## 列挙型"
 
-#. type: Bullet: '   - '
-#: doc/rust.md:136
-msgid "The remaining characters have property `XID_continue`"
-msgstr ""
+#. type: Plain text
+#: doc/rust.md:1204
+#, fuzzy
+#| msgid "## Structs"
+msgid "### Static items"
+msgstr "## 構造体"
 
 #. type: Plain text
-#: doc/rust.md:138
-msgid "that does _not_ occur in the set of [keywords](#keywords)."
-msgstr ""
+#: doc/rust.md:1240
+#, fuzzy
+#| msgid "# Move semantics"
+msgid "#### Mutable statics"
+msgstr "# ムーブセマンティクス"
 
 #. type: Plain text
-#: doc/rust.md:142
-msgid ""
-"Note: `XID_start` and `XID_continue` as character properties cover the "
-"character ranges used to form the more familiar C and Java language-family "
-"identifiers."
-msgstr ""
+#: doc/rust.md:1274
+#, fuzzy
+#| msgid "## Traits"
+msgid "### Traits"
+msgstr "## トレイト"
 
 #. type: Plain text
-#: doc/rust.md:144
-msgid "### Delimiter-restricted productions"
-msgstr ""
+#: doc/rust.md:1363
+#, fuzzy
+#| msgid "Enum variants may also be structs. For example:"
+msgid "Traits may inherit from other traits. For example, in"
+msgstr "以下の例のように、列挙型バリアントを構造体にすることも可能です。"
 
 #. type: Plain text
-#: doc/rust.md:146
+#: doc/rust.md:1368
+#, fuzzy
+#| msgid ""
+#| "~~~~ trait Shape { fn area(&self) -> f64; } trait Circle : Shape { fn "
+#| "radius(&self) -> f64; } ~~~~"
 msgid ""
-"Some productions are defined by exclusion of particular Unicode characters:"
+"~~~~ trait Shape { fn area() -> f64; } trait Circle : Shape { fn radius() -> "
+"f64; } ~~~~"
 msgstr ""
+"~~~~\n"
+"trait Shape { fn area(&self) -> f64; }\n"
+"trait Circle : Shape { fn radius(&self) -> f64; }\n"
+"~~~~"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:153
-msgid "`non_null` is any single Unicode character aside from `U+0000` (null)"
+#. type: Plain text
+#: doc/rust.md:1377
+#, fuzzy
+#| msgid ""
+#| "In type-parameterized functions, methods of the supertrait may be called "
+#| "on values of subtrait-bound type parameters.  Refering to the previous "
+#| "example of `trait Circle : Shape`:"
+msgid ""
+"In type-parameterized functions, methods of the supertrait may be called on "
+"values of subtrait-bound type parameters.  Referring to the previous example "
+"of `trait Circle : Shape`:"
 msgstr ""
+"型パラメータを持つ関数では、サブトレイトの境界型パラメータの値によりスーパー"
+"トレイトのメソッドを呼び出すことになります。前の例の `trait Circle : Shape` "
+"を参照してください。"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:153
-msgid "`non_eol` is `non_null` restricted to exclude `U+000A` (`'\\n'`)"
+#. type: Plain text
+#: doc/rust.md:1386
+#, fuzzy, no-wrap
+#| msgid ""
+#| "~~~\n"
+#| "# trait Shape { fn area(&self) -> f64; }\n"
+#| "# trait Circle : Shape { fn radius(&self) -> f64; }\n"
+#| "fn radius_times_area<T: Circle>(c: T) -> f64 {\n"
+#| "    // `c` is both a Circle and a Shape\n"
+#| "    c.radius() * c.area()\n"
+#| "}\n"
+#| "~~~\n"
+msgid ""
+"~~~~\n"
+"# trait Shape { fn area(&self) -> f64; }\n"
+"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
+"fn radius_times_area<T: Circle>(c: T) -> f64 {\n"
+"    // `c` is both a Circle and a Shape\n"
+"    c.radius() * c.area()\n"
+"}\n"
+"~~~~\n"
 msgstr ""
+"~~~\n"
+"# trait Shape { fn area(&self) -> f64; }\n"
+"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
+"fn radius_times_area<T: Circle>(c: T) -> f64 {\n"
+"    // `c` は Circle でもあり、Shape でもある\n"
+"    c.radius() * c.area()\n"
+"}\n"
+"~~~\n"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:153
-msgid "`non_star` is `non_null` restricted to exclude `U+002A` (`*`)"
+#. type: Plain text
+#: doc/rust.md:1388 doc/tutorial.md:2508
+msgid "Likewise, supertrait methods may also be called on trait objects."
 msgstr ""
+"同様に、スーパートレイトのメソッドは、トレイトオブジェクトについても呼び出す"
+"ことが可能です。"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:153
+#. type: Plain text
+#: doc/rust.md:1395
+#, fuzzy
+#| msgid ""
+#| "~~~ {.xfail-test} use std::f64::consts::pi; # trait Shape { fn "
+#| "area(&self) -> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } "
+#| "# struct Point { x: f64, y: f64 } # struct CircleStruct { center: Point, "
+#| "radius: f64 } # impl Circle for CircleStruct { fn radius(&self) -> f64 "
+#| "{ (self.area() / pi).sqrt() } } # impl Shape for CircleStruct { fn "
+#| "area(&self) -> f64 { pi * square(self.radius) } }"
 msgid ""
-"`non_slash_or_star` is `non_null` restricted to exclude `U+002F` (`/`) and `U"
-"+002A` (`*`)"
+"~~~~ {.xfail-test} # trait Shape { fn area(&self) -> f64; } # trait Circle : "
+"Shape { fn radius(&self) -> f64; } # impl Shape for int { fn area(&self) -> "
+"f64 { 0.0 } } # impl Circle for int { fn radius(&self) -> f64 { 0.0 } } # "
+"let mycircle = 0;"
 msgstr ""
-
-#. type: Bullet: '  - '
-#: doc/rust.md:153
-msgid "`non_single_quote` is `non_null` restricted to exclude `U+0027` (`'`)"
+"~~~ {.xfail-test}\n"
+"use std::f64::consts::pi;\n"
+"# trait Shape { fn area(&self) -> f64; }\n"
+"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
+"# struct Point { x: f64, y: f64 }\n"
+"# struct CircleStruct { center: Point, radius: f64 }\n"
+"# impl Circle for CircleStruct { fn radius(&self) -> f64 { (self.area() / "
+"pi).sqrt() } }\n"
+"# impl Shape for CircleStruct { fn area(&self) -> f64 { pi * square(self."
+"radius) } }"
+
+#. type: Plain text
+#: doc/rust.md:1399
+#, fuzzy
+#| msgid ""
+#| "let concrete = @CircleStruct{center:Point{x:3f,y:4f},radius:5f}; let "
+#| "mycircle: @Circle = concrete as @Circle; let nonsense = mycircle.radius() "
+#| "* mycircle.area(); ~~~"
+msgid ""
+"let mycircle: Circle = @mycircle as @Circle; let nonsense = mycircle."
+"radius() * mycircle.area(); ~~~~"
 msgstr ""
+"let concrete = @CircleStruct{center:Point{x:3f,y:4f},radius:5f};\n"
+"let mycircle: @Circle = concrete as @Circle;\n"
+"let nonsense = mycircle.radius() * mycircle.area();\n"
+"~~~"
 
-#. type: Bullet: '  - '
-#: doc/rust.md:153
-msgid "`non_double_quote` is `non_null` restricted to exclude `U+0022` (`\"`)"
-msgstr ""
+#. type: Plain text
+#: doc/rust.md:1401
+#, fuzzy
+#| msgid "# Introduction"
+msgid "### Implementations"
+msgstr "# イントロダクション"
 
 #. type: Plain text
-#: doc/rust.md:155
-msgid "## Comments"
-msgstr ""
+#: doc/rust.md:1841
+#, fuzzy
+#| msgid "## Traits"
+msgid "#### Traits"
+msgstr "## トレイト"
 
 #. type: Plain text
-#: doc/rust.md:162
-msgid ""
-"~~~~~~~~ {.ebnf .gram} comment : block_comment | line_comment ; "
-"block_comment : \"/*\" block_comment_body * '*' + '/' ; block_comment_body : "
-"non_star * | '*' + non_slash_or_star ; line_comment : \"//\" non_eol * ; "
-"~~~~~~~~"
-msgstr ""
+#: doc/rust.md:1882
+#, fuzzy
+#| msgid "## Operators"
+msgid "#### Operations"
+msgstr "## 演算子"
 
 #. type: Plain text
-#: doc/rust.md:165
-msgid ""
-"Comments in Rust code follow the general C++ style of line and block-comment "
-"forms, with no nesting of block-comment delimiters."
+#: doc/rust.md:1930
+#, fuzzy
+#| msgid "Our example crate declared this set of `link` attributes:"
+msgid "There are three different types of inline attributes:"
 msgstr ""
+"先ほどのクレートの例では、 `link` 属性は以下のように宣言されていました。"
 
 #. type: Plain text
-#: doc/rust.md:170
-msgid ""
-"Line comments beginning with _three_ slashes (`///`), and block comments "
-"beginning with a repeated asterisk in the block-open sequence (`/**`), are "
-"interpreted as a special syntax for `doc` [attributes](#attributes).  That "
-"is, they are equivalent to writing `#[doc \"...\"]` around the comment's "
-"text."
-msgstr ""
+#: doc/rust.md:1936
+#, fuzzy
+#| msgid "## Freezing"
+msgid "### Deriving"
+msgstr "## 凍結"
 
 #. type: Plain text
-#: doc/rust.md:172
-msgid "Non-doc comments are interpreted as a form of whitespace."
-msgstr ""
+#: doc/rust.md:2038
+#, fuzzy
+#| msgid "## Crates"
+msgid "### Compiler Features"
+msgstr "## クレート"
 
 #. type: Plain text
-#: doc/rust.md:174
-msgid "## Whitespace"
-msgstr ""
+#: doc/rust.md:2126
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "# Statements and expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:179
-msgid ""
-"~~~~~~~~ {.ebnf .gram} whitespace_char : '\\x20' | '\\x09' | '\\x0a' | "
-"'\\x0d' ; whitespace : [ whitespace_char | comment ] + ; ~~~~~~~~"
-msgstr ""
+#: doc/rust.md:2138
+#, fuzzy
+#| msgid "## Structs"
+msgid "## Statements"
+msgstr "## 構造体"
 
 #. type: Plain text
-#: doc/rust.md:183
-msgid ""
-"The `whitespace_char` production is any nonempty Unicode string consisting "
-"of any of the following Unicode characters: `U+0020` (space, `' '`), `U"
-"+0009` (tab, `'\\t'`), `U+000A` (LF, `'\\n'`), `U+000D` (CR, `'\\r'`)."
-msgstr ""
+#: doc/rust.md:2147
+#, fuzzy
+#| msgid "## Declaring and implementing traits"
+msgid "### Declaration statements"
+msgstr "## トレイトの宣言と実装"
 
 #. type: Plain text
-#: doc/rust.md:186
-msgid ""
-"Rust is a \"free-form\" language, meaning that all forms of whitespace serve "
-"only to separate _tokens_ in the grammar, and have no semantic significance."
-msgstr ""
+#: doc/rust.md:2152
+#, fuzzy
+#| msgid "## Operators"
+msgid "#### Item declarations"
+msgstr "## 演算子"
 
 #. type: Plain text
-#: doc/rust.md:189
-msgid ""
-"A Rust program has identical meaning if each whitespace element is replaced "
-"with any other legal whitespace element, such as a single space character."
-msgstr ""
+#: doc/rust.md:2164
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "#### Slot declarations"
+msgstr "## 他のクレートの利用"
 
 #. type: Plain text
-#: doc/rust.md:191
-msgid "## Tokens"
-msgstr ""
+#: doc/rust.md:2177
+#, fuzzy
+#| msgid "## Expressions and semicolons"
+msgid "### Expression statements"
+msgstr "## 式とセミコロン"
 
 #. type: Plain text
-#: doc/rust.md:196
-msgid ""
-"~~~~~~~~ {.ebnf .gram} simple_token : keyword | unop | binop ; token : "
-"simple_token | ident | literal | symbol | whitespace token ; ~~~~~~~~"
-msgstr ""
+#: doc/rust.md:2184
+#, fuzzy
+#| msgid "## Expressions and semicolons"
+msgid "## Expressions"
+msgstr "## 式とセミコロン"
 
 #. type: Plain text
-#: doc/rust.md:201
-msgid ""
-"Tokens are primitive productions in the grammar defined by regular (non-"
-"recursive) languages. \"Simple\" tokens are given in [string table "
-"production](#string-table-productions) form, and occur in the rest of the "
-"grammar as double-quoted strings. Other tokens have exact rules given."
-msgstr ""
+#: doc/rust.md:2238
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Literal expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:203
-msgid "### Keywords"
-msgstr ""
+#: doc/rust.md:2251
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Path expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:205
-msgid "The keywords are the following strings:"
-msgstr ""
+#: doc/rust.md:2256
+#, fuzzy
+#| msgid "## Tuples"
+msgid "### Tuple expressions"
+msgstr "## タプル"
 
 #. type: Plain text
-#: doc/rust.md:222
-msgid ""
-"~~~~~~~~ {.keyword} as break do else enum extern false fn for if impl let "
-"loop match mod mut priv pub ref return self static struct super true trait "
-"type unsafe use while ~~~~~~~~"
-msgstr ""
+#: doc/rust.md:2268
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Structure expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:225
+#: doc/rust.md:2320
+#, fuzzy
+#| msgid ""
+#| "~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: "
+#| "20f }; println(fmt!(\"%f\", point.x)); ~~~"
 msgid ""
-"Each of these keywords has special meaning in its grammar, and all of them "
-"are excluded from the `ident` rule."
+"~~~~ # struct Point3d { x: int, y: int, z: int } let base = Point3d {x: 1, "
+"y: 2, z: 3}; Point3d {y: 0, z: 10, .. base}; ~~~~"
 msgstr ""
+"~~~\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let point = &@~Point { x: 10f, y: 20f };\n"
+"println(fmt!(\"%f\", point.x));\n"
+"~~~"
 
 #. type: Plain text
-#: doc/rust.md:227
-msgid "### Literals"
-msgstr ""
+#: doc/rust.md:2341
+#, fuzzy
+#| msgid "## Operators"
+msgid "### Field expressions"
+msgstr "## 演算子"
 
 #. type: Plain text
-#: doc/rust.md:233
-msgid ""
-"A literal is an expression consisting of a single token, rather than a "
-"sequence of tokens, that immediately and directly denotes the value it "
-"evaluates to, rather than referring to it by name or some other evaluation "
-"rule. A literal is a form of constant expression, so is evaluated "
-"(primarily)  at compile time."
-msgstr ""
+#: doc/rust.md:2362
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Vector expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:237
-msgid ""
-"~~~~~~~~ {.ebnf .gram} literal : string_lit | char_lit | num_lit ; ~~~~~~~~"
-msgstr ""
+#: doc/rust.md:2384
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Index expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:239
-msgid "#### Character and string literals"
+#: doc/rust.md:2400
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~~ {.xfail-test} # use std::task; # do task::spawn {"
 msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
 
 #. type: Plain text
-#: doc/rust.md:243
-msgid ""
-"~~~~~~~~ {.ebnf .gram} char_lit : '\\x27' char_body '\\x27' ; string_lit : "
-"'\"' string_body * '\"' ;"
-msgstr ""
+#: doc/rust.md:2433
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "### Binary operator expressions"
+msgstr "## 他のクレートの利用"
 
 #. type: Plain text
-#: doc/rust.md:246
-#, no-wrap
-msgid ""
-"char_body : non_single_quote\n"
-"          | '\\x5c' [ '\\x27' | common_escape ] ;\n"
-msgstr ""
+#: doc/rust.md:2442
+#, fuzzy
+#| msgid "## Operators"
+msgid "#### Arithmetic operators"
+msgstr "## 演算子"
 
 #. type: Plain text
-#: doc/rust.md:249
-#, no-wrap
-msgid ""
-"string_body : non_double_quote\n"
-"            | '\\x5c' [ '\\x22' | common_escape ] ;\n"
-msgstr ""
+#: doc/rust.md:2465
+#, fuzzy
+#| msgid "## Operators"
+msgid "#### Bitwise operators"
+msgstr "## 演算子"
 
 #. type: Plain text
-#: doc/rust.md:255
-#, no-wrap
-msgid ""
-"common_escape : '\\x5c'\n"
-"              | 'n' | 'r' | 't'\n"
-"              | 'x' hex_digit 2\n"
-"              | 'u' hex_digit 4\n"
-"              | 'U' hex_digit 8 ;\n"
-msgstr ""
+#: doc/rust.md:2497
+#, fuzzy
+#| msgid "# Control structures"
+msgid "#### Comparison operators"
+msgstr "# 制御構造"
 
 #. type: Plain text
-#: doc/rust.md:263
-#, no-wrap
-msgid ""
-"hex_digit : 'a' | 'b' | 'c' | 'd' | 'e' | 'f'\n"
-"          | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'\n"
-"          | dec_digit ;\n"
-"dec_digit : '0' | nonzero_dec ;\n"
-"nonzero_dec: '1' | '2' | '3' | '4'\n"
-"           | '5' | '6' | '7' | '8' | '9' ;\n"
-"~~~~~~~~\n"
-msgstr ""
+#: doc/rust.md:2524
+#, fuzzy
+#| msgid "## Tuple structs"
+msgid "#### Type cast expressions"
+msgstr "## タプル構造体"
 
 #. type: Plain text
-#: doc/rust.md:267
-msgid ""
-"A _character literal_ is a single Unicode character enclosed within two `U"
-"+0027` (single-quote) characters, with the exception of `U+0027` itself, "
-"which must be _escaped_ by a preceding U+005C character (`\\`)."
+#: doc/rust.md:2557
+#, fuzzy
+#| msgid "~~~~ let hi = \"hi\"; let mut count = 0;"
+msgid "~~~~ # let mut x = 0; # let y = 0;"
 msgstr ""
+"~~~~\n"
+" let hi = \"hi\";\n"
+" let mut count = 0;"
 
 #. type: Plain text
-#: doc/rust.md:271
-msgid ""
-"A _string literal_ is a sequence of any Unicode characters enclosed within "
-"two `U+0022` (double-quote) characters, with the exception of `U+0022` "
-"itself, which must be _escaped_ by a preceding `U+005C` character (`\\`)."
-msgstr ""
+#: doc/rust.md:2571
+#, fuzzy
+#| msgid "## Operators"
+msgid "#### Operator precedence"
+msgstr "## 演算子"
 
 #. type: Plain text
-#: doc/rust.md:275
-msgid ""
-"Some additional _escapes_ are available in either character or string "
-"literals. An escape starts with a `U+005C` (`\\`) and continues with one of "
-"the following forms:"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:290
-msgid ""
-"An _8-bit codepoint escape_ escape starts with `U+0078` (`x`) and is "
-"followed by exactly two _hex digits_. It denotes the Unicode codepoint equal "
-"to the provided hex value."
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:290
-msgid ""
-"A _16-bit codepoint escape_ starts with `U+0075` (`u`) and is followed by "
-"exactly four _hex digits_. It denotes the Unicode codepoint equal to the "
-"provided hex value."
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:290
-msgid ""
-"A _32-bit codepoint escape_ starts with `U+0055` (`U`) and is followed by "
-"exactly eight _hex digits_. It denotes the Unicode codepoint equal to the "
-"provided hex value."
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:290
-msgid ""
-"A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072` "
-"(`r`), or `U+0074` (`t`), denoting the unicode values `U+000A` (LF), `U"
-"+000D` (CR) or `U+0009` (HT) respectively."
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:290
-msgid ""
-"The _backslash escape_ is the character U+005C (`\\`) which must be escaped "
-"in order to denote *itself*."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:292
-msgid "#### Number literals"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:294 doc/rust.md:406 doc/rust.md:473
-msgid "~~~~~~~~ {.ebnf .gram}"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:299
-#, no-wrap
-msgid ""
-"num_lit : nonzero_dec [ dec_digit | '_' ] * num_suffix ?\n"
-"        | '0' [       [ dec_digit | '_' ] + num_suffix ?\n"
-"              | 'b'   [ '1' | '0' | '_' ] + int_suffix ?\n"
-"              | 'x'   [ hex_digit | '_' ] + int_suffix ? ] ;\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:301
-msgid "num_suffix : int_suffix | float_suffix ;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:305
-#, no-wrap
-msgid ""
-"int_suffix : 'u' int_suffix_size ?\n"
-"           | 'i' int_suffix_size ? ;\n"
-"int_suffix_size : [ '8' | '1' '6' | '3' '2' | '6' '4' ] ;\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:311
-msgid ""
-"float_suffix : [ exponent | '.' dec_lit exponent ? ] ? float_suffix_ty ? ; "
-"float_suffix_ty : 'f' [ '3' '2' | '6' '4' ] ; exponent : ['E' | 'e'] ['-' | "
-"'+' ] ? dec_lit ; dec_lit : [ dec_digit | '_' ] + ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:315
-msgid ""
-"A _number literal_ is either an _integer literal_ or a _floating-point "
-"literal_. The grammar for recognizing the two kinds of literals is mixed, as "
-"they are differentiated by suffixes."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:317
-msgid "##### Integer literals"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:319
-msgid "An _integer literal_ has one of three forms:"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:326
-msgid ""
-"A _decimal literal_ starts with a *decimal digit* and continues with any "
-"mixture of *decimal digits* and _underscores_."
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:326
-msgid ""
-"A _hex literal_ starts with the character sequence `U+0030` `U+0078` (`0x`) "
-"and continues as any mixture hex digits and underscores."
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:326
-msgid ""
-"An _octal literal_ starts with the character sequence `U+0030` `U+006F` (`0o`) "
-"and continues as any mixture octal digits and underscores."
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:326
-msgid ""
-"A _binary literal_ starts with the character sequence `U+0030` `U+0062` "
-"(`0b`) and continues as any mixture binary digits and underscores."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:330
-msgid ""
-"An integer literal may be followed (immediately, without any spaces) by an "
-"_integer suffix_, which changes the type of the literal. There are two kinds "
-"of integer literal suffix:"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:336
-msgid ""
-"The `i` and `u` suffixes give the literal type `int` or `uint`, respectively."
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:336
-msgid ""
-"Each of the signed and unsigned machine types `u8`, `i8`, `u16`, `i16`, "
-"`u32`, `i32`, `u64` and `i64` give the literal the corresponding machine "
-"type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:343
-msgid ""
-"The type of an _unsuffixed_ integer literal is determined by type "
-"inference.  If a integer type can be _uniquely_ determined from the "
-"surrounding program context, the unsuffixed integer literal has that type.  "
-"If the program context underconstrains the type, the unsuffixed integer "
-"literal's type is `int`; if the program context overconstrains the type, it "
-"is considered a static type error."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:345
-msgid "Examples of integer literals of various forms:"
-msgstr ""
+#: doc/rust.md:2611
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Call expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:350
-#, no-wrap
+#: doc/rust.md:2632
+#, fuzzy
+#| msgid ""
+#| "~~~~ let x: f64 = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
 msgid ""
-"~~~~\n"
-"123; 0xff00;                       // type determined by program context\n"
-"                                   // defaults to int in absence of type\n"
-"                                   // information\n"
+"let x: int = add(1, 2); let pi: Option<f32> = FromStr::from_str(\"3.14\"); "
+"~~~~"
 msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:356
-#, no-wrap
-msgid ""
-"123u;                              // type uint\n"
-"123_u;                             // type uint\n"
-"0xff_u8;                           // type u8\n"
-"0o70_i16;                          // type i16\n"
-"0b1111_1111_1001_0000_i32;         // type i32\n"
 "~~~~\n"
-msgstr ""
+"let x: f64 = 4.0;\n"
+"let y: uint = x as uint;\n"
+"assert!(y == 4u);\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/rust.md:358
-msgid "##### Floating-point literals"
-msgstr ""
+#: doc/rust.md:2634
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Lambda expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:360
-msgid "A _floating-point literal_ has one of two forms:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:365
-msgid ""
-"Two _decimal literals_ separated by a period character `U+002E` (`.`), with "
-"an optional _exponent_ trailing after the second decimal literal."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:365
-msgid "A single _decimal literal_ followed by an _exponent_."
-msgstr ""
+#: doc/rust.md:2677
+#, fuzzy
+#| msgid "## Loops"
+msgid "### While loops"
+msgstr "## ループ"
 
 #. type: Plain text
-#: doc/rust.md:372
-msgid ""
-"By default, a floating-point literal is of type `float`. A floating-point "
-"literal may be followed (immediately, without any spaces) by a _floating-"
-"point suffix_, which changes the type of the literal. There are three "
-"floating-point suffixes: `f` (for the base `float` type), `f32`, and `f64` "
-"(the 32-bit and 64-bit floating point types)."
-msgstr ""
+#: doc/rust.md:2688
+#, fuzzy
+#| msgid "## A minimal example"
+msgid "An example:"
+msgstr "## 最小限の例"
 
 #. type: Plain text
-#: doc/rust.md:374
-msgid "Examples of floating-point literals of various forms:"
+#: doc/rust.md:2691
+#, fuzzy
+#| msgid "~~~~ let hi = \"hi\"; let mut count = 0;"
+msgid "~~~~ let mut i = 0;"
 msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:382
-#, no-wrap
-msgid ""
-"~~~~\n"
-"123.0;                             // type float\n"
-"0.1;                               // type float\n"
-"3f;                                // type float\n"
-"0.1f32;                            // type f32\n"
-"12E+99_f64;                        // type f64\n"
 "~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:384
-msgid "##### Unit and boolean literals"
-msgstr ""
+" let hi = \"hi\";\n"
+" let mut count = 0;"
 
 #. type: Plain text
-#: doc/rust.md:387
-msgid ""
-"The _unit value_, the only value of the type that has the same name, is "
-"written as `()`.  The two values of the boolean type are written `true` and "
-"`false`."
-msgstr ""
+#: doc/rust.md:2699
+#, fuzzy
+#| msgid "## Loops"
+msgid "### Infinite loops"
+msgstr "## ループ"
 
 #. type: Plain text
-#: doc/rust.md:389
-msgid "### Symbols"
-msgstr ""
+#: doc/rust.md:2714
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Break expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:395
-#, no-wrap
-msgid ""
-"~~~~~~~~ {.ebnf .gram}\n"
-"symbol : \"::\" \"->\"\n"
-"       | '#' | '[' | ']' | '(' | ')' | '{' | '}'\n"
-"       | ',' | ';' ;\n"
-"~~~~~~~~\n"
-msgstr ""
+#: doc/rust.md:2727
+#, fuzzy
+#| msgid "# Control structures"
+msgid "### Continue expressions"
+msgstr "# 制御構造"
 
 #. type: Plain text
-#: doc/rust.md:401
-msgid ""
-"Symbols are a general class of printable [token](#tokens) that play "
-"structural roles in a variety of grammar productions. They are catalogued "
-"here for completeness as the set of remaining miscellaneous printable tokens "
-"that do not otherwise appear as [unary operators](#unary-operator-"
-"expressions), [binary operators](#binary-operator-expressions), or [keywords]"
-"(#keywords)."
-msgstr ""
+#: doc/rust.md:2746
+#, fuzzy
+#| msgid "## Conventions"
+msgid "### Do expressions"
+msgstr "## 本書の表記について"
 
 #. type: Plain text
-#: doc/rust.md:404
-msgid "## Paths"
-msgstr ""
+#: doc/rust.md:2792
+#, fuzzy
+#| msgid "## Freezing"
+msgid "### For expressions"
+msgstr "## 凍結"
 
 #. type: Plain text
-#: doc/rust.md:410
-#, no-wrap
-msgid ""
-"expr_path : ident [ \"::\" expr_path_tail ] + ;\n"
-"expr_path_tail : '<' type_expr [ ',' type_expr ] + '>'\n"
-"               | expr_path ;\n"
-msgstr ""
+#: doc/rust.md:2826
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### If expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:414
-#, no-wrap
-msgid ""
-"type_path : ident [ type_path_tail ] + ;\n"
-"type_path_tail : '<' type_expr [ ',' type_expr ] + '>'\n"
-"               | \"::\" type_path ;\n"
-msgstr ""
+#: doc/rust.md:2847
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Match expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:421
-msgid ""
-"A _path_ is a sequence of one or more path components _logically_ separated "
-"by a namespace qualifier (`::`). If a path consists of only one component, "
-"it may refer to either an [item](#items) or a [slot](#memory-slots) in a "
-"local control scope. If a path has multiple components, it refers to an item."
+#: doc/rust.md:2940
+#, fuzzy
+#| msgid "~~~~ # let mystery_object = ();"
+msgid "~~~~ # let x = 2;"
 msgstr ""
+"~~~~\n"
+"# let mystery_object = ();"
 
 #. type: Plain text
-#: doc/rust.md:425
-msgid ""
-"Every item has a _canonical path_ within its crate, but the path naming an "
-"item is only meaningful within a given crate. There is no global namespace "
-"across crates; an item's canonical path merely identifies it within the "
-"crate."
-msgstr ""
+#: doc/rust.md:2970
+#, fuzzy
+#| msgid "## Syntax extensions"
+msgid "### Return expressions"
+msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/rust.md:427
-msgid "Two examples of simple paths consisting of only identifier components:"
-msgstr ""
+#: doc/rust.md:2994
+#, fuzzy
+#| msgid "## Tuples"
+msgid "## Types"
+msgstr "## タプル"
 
 #. type: Plain text
-#: doc/rust.md:432
-msgid "~~~~{.ignore} x; x::y::z; ~~~~"
-msgstr ""
+#: doc/rust.md:3003
+#, fuzzy
+#| msgid "## Primitive types and literals"
+msgid "### Primitive types"
+msgstr "## プリミティブ型とリテラル"
 
 #. type: Plain text
-#: doc/rust.md:439
-msgid ""
-"Path components are usually [identifiers](#identifiers), but the trailing "
-"component of a path may be an angle-bracket-enclosed list of type arguments. "
-"In [expression](#expressions) context, the type argument list is given after "
-"a final (`::`) namespace qualifier in order to disambiguate it from a "
-"relational expression involving the less-than symbol (`<`). In type "
-"expression context, the final namespace qualifier is omitted."
-msgstr ""
+#: doc/rust.md:3005
+#, fuzzy
+#| msgid "## Primitive types and literals"
+msgid "The primitive types are the following:"
+msgstr "## プリミティブ型とリテラル"
 
 #. type: Plain text
-#: doc/rust.md:441
-msgid "Two examples of paths with type arguments:"
-msgstr ""
+#: doc/rust.md:3013
+#, fuzzy
+#| msgid "# Closures"
+msgid "#### Machine types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:450
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# use std::hashmap::HashMap;\n"
-"# fn f() {\n"
-"# fn id<T>(t: T) -> T { t }\n"
-"type t = HashMap<int,~str>;  // Type arguments used in a type expression\n"
-"let x = id::<int>(10);         // Type arguments used in a call expression\n"
-"# }\n"
-"~~~~\n"
-msgstr ""
+#: doc/rust.md:3041
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Textual types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:452
-msgid "# Syntax extensions"
-msgstr ""
+#: doc/rust.md:3054
+#, fuzzy
+#| msgid "## Tuples"
+msgid "### Tuple types"
+msgstr "## タプル"
 
 #. type: Plain text
-#: doc/rust.md:457
-msgid ""
-"A number of minor features of Rust are not central enough to have their own "
-"syntax, and yet are not implementable as functions. Instead, they are given "
-"names, and invoked through a consistent syntax: `name!(...)`. Examples "
-"include:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:466
-msgid "`fmt!` : format data into a string"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:466
-msgid "`env!` : look up an environment variable's value at compile time"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:466
-msgid "`stringify!` : pretty-print the Rust expression given as an argument"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:466
-msgid "`proto!` : define a protocol for inter-task communication"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:466
-msgid "`include!` : include the Rust expression in the given file"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:466
-msgid "`include_str!` : include the contents of the given file as a string"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:466
-msgid ""
-"`include_bin!` : include the contents of the given file as a binary blob"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:466
-msgid "`error!`, `warn!`, `info!`, `debug!` : provide diagnostic information."
-msgstr ""
+#: doc/rust.md:3078
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Vector types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:469
+#: doc/rust.md:3102
+#, fuzzy
+#| msgid ""
+#| "~~~~ let x: f64 = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
 msgid ""
-"All of the above extensions, with the exception of `proto!`, are expressions "
-"with values. `proto!` is an item, defining a new name."
+"~~~~ let v: &[int] = &[7, 5, 3]; let i: int = v[2]; assert!(i == 3); ~~~~"
 msgstr ""
+"~~~~\n"
+"let x: f64 = 4.0;\n"
+"let y: uint = x as uint;\n"
+"assert!(y == 4u);\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/rust.md:471
-msgid "## Macros"
-msgstr ""
+#: doc/rust.md:3107
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Structure types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:484
-#, no-wrap
-msgid ""
-"expr_macro_rules : \"macro_rules\" '!' ident '(' macro_rule * ')'\n"
-"macro_rule : '(' matcher * ')' \"=>\" '(' transcriber * ')' ';'\n"
-"matcher : '(' matcher * ')' | '[' matcher * ']'\n"
-"        | '{' matcher * '}' | '$' ident ':' ident\n"
-"        | '$' '(' matcher * ')' sep_token? [ '*' | '+' ]\n"
-"        | non_special_token\n"
-"transcriber : '(' transcriber * ')' | '[' transcriber * ']'\n"
-"            | '{' transcriber * '}' | '$' ident\n"
-"            | '$' '(' transcriber * ')' sep_token? [ '*' | '+' ]\n"
-"            | non_special_token\n"
-msgstr ""
+#: doc/rust.md:3128
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Enumerated types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:490
-msgid ""
-"User-defined syntax extensions are called \"macros\", and the `macro_rules` "
-"syntax extension defines them.  Currently, user-defined macros can expand to "
-"expressions, statements, or items."
-msgstr ""
+#: doc/rust.md:3146
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Recursive types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:493
-msgid ""
-"(A `sep_token` is any token other than `*` and `+`.  A `non_special_token` "
-"is any token other than a delimiter or `$`.)"
-msgstr ""
+#: doc/rust.md:3173
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Pointer types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:499
-msgid ""
-"The macro expander looks up macro invocations by name, and tries each macro "
-"rule in turn.  It transcribes the first successful match.  Matching and "
-"transcription are closely related to each other, and we will describe them "
-"together."
-msgstr ""
+#: doc/rust.md:3221
+#, fuzzy
+#| msgid "# Functions"
+msgid "### Function types"
+msgstr "# 関数"
 
 #. type: Plain text
-#: doc/rust.md:501
-msgid "### Macro By Example"
-msgstr ""
+#: doc/rust.md:3241
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Closure types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:504
-msgid ""
-"The macro expander matches and transcribes every token that does not begin "
-"with a `$` literally, including delimiters.  For parsing reasons, delimiters "
-"must be balanced, but they are otherwise not special."
+#: doc/rust.md:3251
+#, fuzzy
+#| msgid ""
+#| "let captured_var = 20; let closure = |arg| println(fmt!(\"captured_var="
+#| "%d, arg=%d\", captured_var, arg));"
+msgid "let closure_no_args = || println!(\"captured_var={}\", captured_var);"
 msgstr ""
+"let captured_var = 20;\n"
+"let closure = |arg| println(fmt!(\"captured_var=%d, arg=%d\", captured_var, "
+"arg));"
 
 #. type: Plain text
-#: doc/rust.md:510
+#: doc/rust.md:3256
+#, fuzzy, no-wrap
+#| msgid "let captured_var = 20; let closure = |arg| println(fmt!(\"captured_var=%d, arg=%d\", captured_var, arg));"
 msgid ""
-"In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the "
-"Rust syntax named by _designator_. Valid designators are `item`, `block`, "
-"`stmt`, `pat`, `expr`, `ty` (type), `ident`, `path`, `matchers` (lhs of the "
-"`=>` in macro rules), `tt` (rhs of the `=>` in macro rules). In the "
-"transcriber, the designator is already known, and so only the name of a "
-"matched nonterminal comes after the dollar sign."
+"let closure_args = |arg: int| -> int {\n"
+"  println!(\"captured_var={}, arg={}\", captured_var, arg);\n"
+"  arg // Note lack of semicolon after 'arg'\n"
+"};\n"
 msgstr ""
+"let captured_var = 20;\n"
+"let closure = |arg| println(fmt!(\"captured_var=%d, arg=%d\", captured_var, arg));"
 
 #. type: Plain text
-#: doc/rust.md:519
-msgid ""
-"In both the matcher and transcriber, the Kleene star-like operator indicates "
-"repetition.  The Kleene star operator consists of `$` and parens, optionally "
-"followed by a separator token, followed by `*` or `+`.  `*` means zero or "
-"more repetitions, `+` means at least one repetition.  The parens are not "
-"matched or transcribed.  On the matcher side, a name is bound to _all_ of "
-"the names it matches, in a structure that mimics the structure of the "
-"repetition encountered on a successful match. The job of the transcriber is "
-"to sort that structure out."
-msgstr ""
+#: doc/rust.md:3267
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Object types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:525
+#: doc/rust.md:3299
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
 msgid ""
-"The rules for transcription of these repetitions are called \"Macro By "
-"Example\".  Essentially, one \"layer\" of repetition is discharged at a "
-"time, and all of them must be discharged by the time a name is transcribed. "
-"Therefore, `( $( $i:ident ),* ) => ( $i )` is an invalid macro, but `( $( $i:"
-"ident ),* ) => ( $( $i:ident ),* )` is acceptable (if trivial)."
+"fn main() {\n"
+"   print(@10 as @Printable);\n"
+"}\n"
+"~~~~\n"
 msgstr ""
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/rust.md:533
-msgid ""
-"When Macro By Example encounters a repetition, it examines all of the `$` "
-"_name_ s that occur in its body. At the \"current layer\", they all must "
-"repeat the same number of times, so ` ( $( $i:ident ),* ; $( $j:ident ),* ) "
-"=> ( $( ($i,$j) ),* )` is valid if given the argument `(a,b,c ; d,e,f)`, but "
-"not `(a,b,c ; d,e)`. The repetition walks through the choices at that layer "
-"in lockstep, so the former input transcribes to `( (a,d), (b,e), (c,f) )`."
-msgstr ""
+#: doc/rust.md:3322
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Self types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:535
-msgid "Nested repetitions are allowed."
-msgstr ""
+#: doc/rust.md:3343
+#, fuzzy
+#| msgid "## Tuples"
+msgid "## Type kinds"
+msgstr "## タプル"
 
 #. type: Plain text
-#: doc/rust.md:537
-msgid "### Parsing limitations"
-msgstr ""
+#: doc/rust.md:3440
+#, fuzzy
+#| msgid "# Ownership"
+msgid "### Memory ownership"
+msgstr "# 所有権"
 
 #. type: Plain text
-#: doc/rust.md:540
-msgid ""
-"The parser used by the macro system is reasonably powerful, but the parsing "
-"of Rust syntax is restricted in two ways:"
-msgstr ""
+#: doc/rust.md:3497
+#, fuzzy
+#| msgid "## Managed boxes"
+msgid "### Memory boxes"
+msgstr "## マネージドボックス"
 
 #. type: Plain text
-#: doc/rust.md:546
-#, no-wrap
-msgid ""
-"1. The parser will always parse as much as possible. If it attempts to match\n"
-"`$i:expr [ , ]` against `8 [ , ]`, it will attempt to parse `i` as an array\n"
-"index operation and fail. Adding a separator can solve this problem.\n"
-"2. The parser must have eliminated all ambiguity by the time it reaches a `$` _name_ `:` _designator_.\n"
-"This requirement most often affects name-designator pairs when they occur at the beginning of, or immediately after, a `$(...)*`; requiring a distinctive token in front can solve the problem.\n"
+#: doc/rust.md:3519
+#, fuzzy
+#| msgid "~~~~ let hi = \"hi\"; let mut count = 0;"
+msgid "~~~~ let x: @int = @10; let x: ~int = ~10; ~~~~"
 msgstr ""
+"~~~~\n"
+" let hi = \"hi\";\n"
+" let mut count = 0;"
 
 #. type: Plain text
-#: doc/rust.md:549
-msgid "## Syntax extensions useful for the macro author"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:554
-msgid "`log_syntax!` : print out the arguments at compile time"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:554
-msgid ""
-"`trace_macros!` : supply `true` or `false` to enable or disable macro "
-"expansion logging"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:554
-msgid "`stringify!` : turn the identifier argument into a string literal"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:554
-msgid ""
-"`concat_idents!` : create a new identifier by concatenating the arguments"
-msgstr ""
+#: doc/rust.md:3555
+#, fuzzy
+#| msgid "## Traits"
+msgid "## Tasks"
+msgstr "## トレイト"
 
 #. type: Plain text
-#: doc/rust.md:556
-msgid "# Crates and source files"
-msgstr ""
+#: doc/rust.md:3580
+#, fuzzy
+#| msgid "## Conditionals"
+msgid "### Communication between tasks"
+msgstr "## 条件式"
 
 #. type: Plain text
-#: doc/rust.md:563
-msgid ""
-"Rust is a *compiled* language.  Its semantics obey a *phase distinction* "
-"between compile-time and run-time.  Those semantic rules that have a *static "
-"interpretation* govern the success or failure of compilation.  We refer to "
-"these rules as \"static semantics\".  Semantic rules called \"dynamic "
-"semantics\" govern the behavior of programs at run-time.  A program that "
-"fails to compile due to violation of a compile-time rule has no defined "
-"dynamic semantics; the compiler should halt with an error report, and "
-"produce no executable artifact."
-msgstr ""
+#: doc/rust.md:3660
+#, fuzzy
+#| msgid "# Introduction"
+msgid "### Memory allocation"
+msgstr "# イントロダクション"
 
 #. type: Plain text
-#: doc/rust.md:569
-msgid ""
-"The compilation model centres on artifacts called _crates_.  Each "
-"compilation processes a single crate in source form, and if successful, "
-"produces a single crate in binary form: either an executable or a library."
-"^[A crate is somewhat analogous to an *assembly* in the ECMA-335 CLI model, "
-"a *library* in the SML/NJ Compilation Manager, a *unit* in the Owens and "
-"Flatt module system, or a *configuration* in Mesa.]"
-msgstr ""
+#: doc/rust.md:3672
+#, fuzzy
+#| msgid "# Closures"
+msgid "### Built in types"
+msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/rust.md:573
-msgid ""
-"A _crate_ is a unit of compilation and linking, as well as versioning, "
-"distribution and runtime loading.  A crate contains a _tree_ of nested "
-"[module](#modules) scopes.  The top level of this tree is a module that is "
-"anonymous (from the point of view of paths within the module) and any item "
-"within a crate has a canonical [module path](#paths) denoting its location "
-"within the crate's module tree."
-msgstr ""
+#: doc/rust.md:3681
+#, fuzzy
+#| msgid "[Tasks and communication][tasks]"
+msgid "### Task scheduling and communication"
+msgstr "[タスクと通信][tasks]"
 
 #. type: Plain text
-#: doc/rust.md:577
-msgid ""
-"The Rust compiler is always invoked with a single source file as input, and "
-"always produces a single output crate.  The processing of that source file "
-"may result in other source files being loaded as modules.  Source files have "
-"the extension `.rs`."
-msgstr ""
+#: doc/rust.md:3689
+#, fuzzy
+#| msgid "## Freezing"
+msgid "### Linkage"
+msgstr "## 凍結"
 
 #. type: Plain text
-#: doc/rust.md:582
-msgid ""
-"A Rust source file describes a module, the name and location of which -- in "
-"the module tree of the current crate -- are defined from outside the source "
-"file: either by an explicit `mod_item` in a referencing source file, or by "
-"the name of the crate itself."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:587
-msgid ""
-"Each source file contains a sequence of zero or more `item` definitions, and "
-"may optionally begin with any number of `attributes` that apply to the "
-"containing module.  Atributes on the anonymous crate module define important "
-"metadata that influences the behavior of the compiler."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:593
-#, no-wrap
-msgid ""
-"~~~~~~~~\n"
-"// Linkage attributes\n"
-"#[ link(name = \"projx\",\n"
-"        vers = \"2.5\",\n"
-"        uuid = \"9cccc5d5-aceb-4af5-8285-811211826b82\") ];\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:598
-msgid ""
-"// Additional metadata attributes #[ desc = \"Project X\" ]; #[ license = "
-"\"BSD\" ]; #[ author = \"Jane Doe\" ];"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:601
-msgid "// Specify the output type #[ crate_type = \"lib\" ];"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:605
-msgid "// Turn on a warning #[ warn(non_camel_case_types) ]; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:608
-msgid ""
-"A crate that contains a `main` function can be compiled to an executable.  "
-"If a `main` function is present, its return type must be [`unit`](#primitive-"
-"types) and it must take no arguments."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:611
-msgid "# Items and attributes"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:614
-msgid ""
-"Crates contain [items](#items), each of which may have some number of "
-"[attributes](#attributes) attached to it."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:616
-msgid "## Items"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:621
-#, no-wrap
-msgid ""
-"~~~~~~~~ {.ebnf .gram}\n"
-"item : mod_item | fn_item | type_item | struct_item | enum_item\n"
-"     | static_item | trait_item | impl_item | extern_block ;\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:627
-msgid ""
-"An _item_ is a component of a crate; some module items can be defined in "
-"crate files, but most are defined in source files. Items are organized "
-"within a crate by a nested set of [modules](#modules). Every crate has a "
-"single \"outermost\" anonymous module; all further items within the crate "
-"have [paths](#paths) within the module tree of the crate."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:630
-msgid ""
-"Items are entirely determined at compile-time, generally remain fixed during "
-"execution, and may reside in read-only memory."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:632
-msgid "There are several kinds of item:"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:641
-msgid "[modules](#modules)"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:641
-msgid "[functions](#functions)"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:641
-msgid "[type definitions](#type-definitions)"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:641
-msgid "[structures](#structures)"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:641
-msgid "[enumerations](#enumerations)"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:641
-msgid "[static items](#static-items)"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:641
-msgid "[traits](#traits)"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:641
-msgid "[implementations](#implementations)"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:651
-msgid ""
-"Some items form an implicit scope for the declaration of sub-items. In other "
-"words, within a function or module, declarations of items can (in many "
-"cases)  be mixed with the statements, control blocks, and similar artifacts "
-"that otherwise compose the item body. The meaning of these scoped items is "
-"the same as if the item was declared outside the scope -- it is still a "
-"static item -- except that the item's *path name* within the module "
-"namespace is qualified by the name of the enclosing item, or is private to "
-"the enclosing item (in the case of functions).  The grammar specifies the "
-"exact locations in which sub-item declarations may appear."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:653
-msgid "### Type Parameters"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:662
-msgid ""
-"All items except modules may be *parameterized* by type. Type parameters are "
-"given as a comma-separated list of identifiers enclosed in angle brackets "
-"(`<...>`), after the name of the item and before its definition.  The type "
-"parameters of an item are considered \"part of the name\", not part of the "
-"type of the item.  A referencing [path](#paths) must (in principle) provide "
-"type arguments as a list of comma-separated types enclosed within angle "
-"brackets, in order to refer to the type-parameterized item.  In practice, "
-"the type-inference system can usually infer such argument types from "
-"context.  There are no general type-parametric types, only type-parametric "
-"items.  That is, Rust has no notion of type abstraction: there are no first-"
-"class \"forall\" types."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:664
-msgid "### Modules"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:669
-msgid ""
-"~~~~~~~~ {.ebnf .gram} mod_item : \"mod\" ident ( ';' | '{' mod '}' ); mod : "
-"[ view_item | item ] * ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:674
-msgid ""
-"A module is a container for zero or more [view items](#view-items) and zero "
-"or more [items](#items). The view items manage the visibility of the items "
-"defined within the module, as well as the visibility of names from outside "
-"the module when referenced from inside the module."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:678
-msgid ""
-"A _module item_ is a module, surrounded in braces, named, and prefixed with "
-"the keyword `mod`. A module item introduces a new, named module into the "
-"tree of modules making up a crate. Modules can nest arbitrarily."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:680
-msgid "An example of a module:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:698
-#, no-wrap
-msgid ""
-"~~~~~~~~\n"
-"mod math {\n"
-"    type complex = (f64, f64);\n"
-"    fn sin(f: f64) -> f64 {\n"
-"        ...\n"
-"# fail!();\n"
-"    }\n"
-"    fn cos(f: f64) -> f64 {\n"
-"        ...\n"
-"# fail!();\n"
-"    }\n"
-"    fn tan(f: f64) -> f64 {\n"
-"        ...\n"
-"# fail!();\n"
-"    }\n"
-"}\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:703
-msgid ""
-"Modules and types share the same namespace.  Declaring a named type that has "
-"the same name as a module in scope is forbidden: that is, a type definition, "
-"trait, struct, enumeration, or type parameter can't shadow the name of a "
-"module in scope, or vice versa."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:708
-msgid ""
-"A module without a body is loaded from an external file, by default with the "
-"same name as the module, plus the `.rs` extension.  When a nested submodule "
-"is loaded from an external file, it is loaded from a subdirectory path that "
-"mirrors the module hierarchy."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:712
-msgid "~~~ {.xfail-test} // Load the `vec` module from `vec.rs` mod vec;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:718
-#, no-wrap
-msgid ""
-"mod task {\n"
-"    // Load the `local_data` module from `task/local_data.rs`\n"
-"    mod local_data;\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:721
-msgid ""
-"The directories and files used for loading external file modules can be "
-"influenced with the `path` attribute."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:730
-#, no-wrap
-msgid ""
-"~~~ {.xfail-test}\n"
-"#[path = \"task_files\"]\n"
-"mod task {\n"
-"    // Load the `local_data` module from `task_files/tls.rs`\n"
-"    #[path = \"tls.rs\"]\n"
-"    mod local_data;\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:732
-msgid "#### View items"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:736
-msgid ""
-"~~~~~~~~ {.ebnf .gram} view_item : extern_mod_decl | use_decl ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:740
-msgid ""
-"A view item manages the namespace of a module.  View items do not define new "
-"items, but rather, simply change other items' visibility.  There are several "
-"kinds of view item:"
-msgstr ""
-
-#. type: Bullet: ' * '
-#: doc/rust.md:743
-msgid "[`extern mod` declarations](#extern-mod-declarations)"
-msgstr ""
-
-#. type: Bullet: ' * '
-#: doc/rust.md:743
-msgid "[`use` declarations](#use-declarations)"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:745
-msgid "##### Extern mod declarations"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:751
-msgid ""
-"~~~~~~~~ {.ebnf .gram} extern_mod_decl : \"extern\" \"mod\" ident [ '(' "
-"link_attrs ')' ] ? [ '=' string_lit ] ? ; link_attrs : link_attr [ ',' "
-"link_attrs ] + ; link_attr : ident '=' literal ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:755
-msgid ""
-"An _`extern mod` declaration_ specifies a dependency on an external crate.  "
-"The external crate is then bound into the declaring scope as the `ident` "
-"provided in the `extern_mod_decl`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:765
-msgid ""
-"The external crate is resolved to a specific `soname` at compile time, and a "
-"runtime linkage requirement to that `soname` is passed to the linker for "
-"loading at runtime.  The `soname` is resolved at compile time by scanning "
-"the compiler's library path and matching the `link_attrs` provided in the "
-"`use_decl` against any `#link` attributes that were declared on the external "
-"crate when it was compiled.  If no `link_attrs` are provided, a default "
-"`name` attribute is assumed, equal to the `ident` given in the `use_decl`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:775
-msgid ""
-"Optionally, an identifier in an `extern mod` declaration may be followed by "
-"an equals sign, then a string literal denoting a relative path on the "
-"filesystem.  This path should exist in one of the directories in the Rust "
-"path, which by default contains the `.rust` subdirectory of the current "
-"directory and each of its parents, as well as any directories in the colon-"
-"separated (or semicolon-separated on Windows)  list of paths that is the "
-"`RUST_PATH` environment variable.  The meaning of `extern mod a = \"b/c/d\";"
-"`, supposing that `/a` is in the RUST_PATH, is that the name `a` should be "
-"taken as a reference to the crate whose absolute location is `/a/b/c/d`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:777
-msgid "Four examples of `extern mod` declarations:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:780
-msgid ""
-"~~~~~~~~{.xfail-test} extern mod pcre (uuid = \"54aba0f8-"
-"a7b1-4beb-92f1-4cf625264841\");"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:782
-msgid ""
-"extern mod extra; // equivalent to: extern mod extra ( name = \"extra\" );"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:784
-msgid ""
-"extern mod rustextra (name = \"extra\"); // linking to 'extra' under another "
-"name"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:787
-msgid "extern mod complicated_mod = \"some-file/in/the-rust/path\"; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:789
-msgid "##### Use declarations"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:793
-#, no-wrap
-msgid ""
-"~~~~~~~~ {.ebnf .gram}\n"
-"use_decl : \"pub\"? \"use\" ident [ '=' path\n"
-"                          | \"::\" path_glob ] ;\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:798
-#, no-wrap
-msgid ""
-"path_glob : ident [ \"::\" path_glob ] ?\n"
-"          | '*'\n"
-"          | '{' ident [ ',' ident ] * '}'\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:802
-msgid ""
-"A _use declaration_ creates one or more local name bindings synonymous with "
-"some other [path](#paths).  Usually a `use` declaration is used to shorten "
-"the path required to refer to a module item."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:806
-#, no-wrap
-msgid ""
-"*Note*: Unlike in many languages,\n"
-"`use` declarations in Rust do *not* declare linkage dependency with external crates.\n"
-"Rather, [`extern mod` declarations](#extern-mod-declarations) declare linkage dependencies.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:808
-msgid "Use declarations support a number of convenient shortcuts:"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:813
-msgid ""
-"Rebinding the target name as a new local name, using the syntax `use x = p::"
-"q::r;`."
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:813
-msgid ""
-"Simultaneously binding a list of paths differing only in their final "
-"element, using the glob-like brace syntax `use a::b::{c,d,e,f};`"
-msgstr ""
-
-#. type: Bullet: '  * '
-#: doc/rust.md:813
-msgid ""
-"Binding all paths matching a given prefix, using the asterisk wildcard "
-"syntax `use a::b::*;`"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:815
-msgid "An example of `use` declarations:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:819
-msgid "~~~~ use std::num::sin; use std::option::{Some, None};"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:823
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"    // Equivalent to 'info!(std::num::sin(1.0));'\n"
-"    info!(sin(1.0));\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:828
-#, no-wrap
-msgid ""
-"    // Equivalent to 'info!(~[std::option::Some(1.0), std::option::None]);'\n"
-"    info!(~[Some(1.0), None]);\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:836
-msgid ""
-"Like items, `use` declarations are private to the containing module, by "
-"default.  Also like items, a `use` declaration can be public, if qualified "
-"by the `pub` keyword.  Such a `use` declaration serves to _re-export_ a "
-"name.  A public `use` declaration can therefore _redirect_ some public name "
-"to a different target definition: even a definition with a private canonical "
-"path, inside a different module.  If a sequence of such redirections form a "
-"cycle or cannot be resolved unambiguously, they represent a compile-time "
-"error."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:842
-#, no-wrap
-msgid ""
-"An example of re-exporting:\n"
-"~~~~\n"
-"# fn main() { }\n"
-"mod quux {\n"
-"    pub use quux::foo::*;\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:849
-#, no-wrap
-msgid ""
-"    pub mod foo {\n"
-"        pub fn bar() { }\n"
-"        pub fn baz() { }\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:851
-msgid ""
-"In this example, the module `quux` re-exports all of the public names "
-"defined in `foo`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:854
-msgid ""
-"Also note that the paths contained in `use` items are relative to the crate "
-"root.  So, in the previous example, the `use` refers to `quux::foo::*`, and "
-"not simply to `foo::*`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:856
-msgid "### Functions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:860
-msgid ""
-"A _function item_ defines a sequence of [statements](#statements) and an "
-"optional final [expression](#expressions), along with a name and a set of "
-"parameters.  Functions are declared with the keyword `fn`.  Functions "
-"declare a set of *input* [*slots*](#memory-slots) as parameters, through "
-"which the caller passes arguments into the function, and an *output* [*slot*]"
-"(#memory-slots) through which the function passes results back to the caller."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:865
-msgid ""
-"A function may also be copied into a first class *value*, in which case the "
-"value has the corresponding [*function type*](#function-types), and can be "
-"used otherwise exactly as a function item (with a minor additional cost of "
-"calling the function indirectly)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:871
-msgid ""
-"Every control path in a function logically ends with a `return` expression "
-"or a diverging expression. If the outermost block of a function has a value-"
-"producing expression in its final-expression position, that expression is "
-"interpreted as an implicit `return` expression applied to the final-"
-"expression."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:873
-msgid "An example of a function:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:879
-#, no-wrap
-msgid ""
-"~~~~\n"
-"fn add(x: int, y: int) -> int {\n"
-"    return x + y;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:882
-msgid ""
-"As with `let` bindings, function arguments are irrefutable patterns, so any "
-"pattern that is valid in a let binding is also valid as an argument."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:886
-msgid "~~~ fn first((value, _): (int, int)) -> int { value } ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:889
-msgid "#### Generic functions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:894
-msgid ""
-"A _generic function_ allows one or more _parameterized types_ to appear in "
-"its signature. Each type parameter must be explicitly declared, in an angle-"
-"bracket-enclosed, comma-separated list following the function name."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:905
-#, no-wrap
-msgid ""
-"~~~~ {.xfail-test}\n"
-"fn iter<T>(seq: &[T], f: |T|) {\n"
-"    for elt in seq.iter() { f(elt); }\n"
-"}\n"
-"fn map<T, U>(seq: &[T], f: |T| -> U) -> ~[U] {\n"
-"    let mut acc = ~[];\n"
-"    for elt in seq.iter() { acc.push(f(elt)); }\n"
-"    acc\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:908
-msgid ""
-"Inside the function signature and body, the name of the type parameter can "
-"be used as a type name."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:914
-msgid ""
-"When a generic function is referenced, its type is instantiated based on the "
-"context of the reference. For example, calling the `iter` function defined "
-"above on `[1, 2]` will instantiate type parameter `T` with `int`, and "
-"require the closure parameter to have type `fn(int)`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:919
-msgid ""
-"The type parameters can also be explicitly supplied in a trailing [path]"
-"(#paths) component after the function name. This might be necessary if there "
-"is not sufficient context to determine the type parameters. For example, "
-"`mem::size_of::<u32>() == 4`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:923
-msgid ""
-"Since a parameter type is opaque to the generic function, the set of "
-"operations that can be performed on it is limited. Values of parameter type "
-"can only be moved, not copied."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:927
-msgid "~~~~ fn id<T>(x: T) -> T { x } ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:931
-msgid ""
-"Similarly, [trait](#traits) bounds can be specified for type parameters to "
-"allow methods with that trait to be called on values of that type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:934
-msgid "#### Unsafe functions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:937
-msgid ""
-"Unsafe functions are those containing unsafe operations that are not "
-"contained in an [`unsafe` block](#unsafe-blocks).  Such a function must be "
-"prefixed with the keyword `unsafe`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:940
-msgid ""
-"Unsafe operations are those that potentially violate the memory-safety "
-"guarantees of Rust's static semantics.  Specifically, the following "
-"operations are considered unsafe:"
-msgstr ""
-
-#. type: Bullet: '  - '
-#: doc/rust.md:944
-msgid "Dereferencing a [raw pointer](#pointer-types)."
-msgstr ""
-
-#. type: Bullet: '  - '
-#: doc/rust.md:944
-msgid "Casting a [raw pointer](#pointer-types) to a safe pointer type."
-msgstr ""
-
-#. type: Bullet: '  - '
-#: doc/rust.md:944
-msgid "Calling an unsafe function."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:946
-msgid "##### Unsafe blocks"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:950
-msgid ""
-"A block of code can also be prefixed with the `unsafe` keyword, to permit a "
-"sequence of unsafe operations in an otherwise-safe function.  This facility "
-"exists because the static semantics of Rust are a necessary approximation of "
-"the dynamic semantics.  When a programmer has sufficient conviction that a "
-"sequence of unsafe operations is actually safe, they can encapsulate that "
-"sequence (taken as a whole) within an `unsafe` block. The compiler will "
-"consider uses of such code \"safe\", to the surrounding context."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:953
-msgid "#### Diverging functions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:956
-msgid ""
-"A special kind of function can be declared with a `!` character where the "
-"output slot type would normally be. For example:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:963
-#, no-wrap
-msgid ""
-"~~~~\n"
-"fn my_err(s: &str) -> ! {\n"
-"    info!(s);\n"
-"    fail!();\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:970
-msgid ""
-"We call such functions \"diverging\" because they never return a value to "
-"the caller. Every control path in a diverging function must end with a `fail!"
-"()` or a call to another diverging function on every control path. The `!` "
-"annotation does *not* denote a type. Rather, the result type of a diverging "
-"function is a special type called $\\bot$ (\"bottom\") that unifies with any "
-"type. Rust has no syntax for $\\bot$."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:976
-msgid ""
-"It might be necessary to declare a diverging function because as mentioned "
-"previously, the typechecker checks that every control path in a function "
-"ends with a [`return`](#return-expressions) or diverging expression. So, if "
-"`my_err` were declared without the `!` annotation, the following code would "
-"not typecheck:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:979
-msgid "~~~~ # fn my_err(s: &str) -> ! { fail!() }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:989
-#, no-wrap
-msgid ""
-"fn f(i: int) -> int {\n"
-"   if i == 42 {\n"
-"     return 42;\n"
-"   }\n"
-"   else {\n"
-"     my_err(\"Bad number!\");\n"
-"   }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:997
-msgid ""
-"This will not compile without the `!` annotation on `my_err`, since the "
-"`else` branch of the conditional in `f` does not return an `int`, as "
-"required by the signature of `f`.  Adding the `!` annotation to `my_err` "
-"informs the typechecker that, should control ever enter `my_err`, no further "
-"type judgments about `f` need to hold, since control will never resume in "
-"any context that relies on those judgments.  Thus the return type on `f` "
-"only needs to reflect the `if` branch of the conditional."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1000
-msgid "#### Extern functions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1007
-msgid ""
-"Extern functions are part of Rust's foreign function interface, providing "
-"the opposite functionality to [external blocks](#external-blocks).  Whereas "
-"external blocks allow Rust code to call foreign code, extern functions with "
-"bodies defined in Rust code _can be called by foreign code_. They are "
-"defined in the same way as any other Rust function, except that they have "
-"the `extern` modifier."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1011
-msgid "~~~ extern fn new_vec() -> ~[int] { ~[] } ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1014
-msgid ""
-"Extern functions may not be called from Rust code, but Rust code may take "
-"their value as a raw `u8` pointer."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1019
-msgid ""
-"~~~ # extern fn new_vec() -> ~[int] { ~[] } let fptr: *u8 = new_vec; ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1023
-msgid ""
-"The primary motivation for extern functions is to create callbacks for "
-"foreign functions that expect to receive function pointers."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1025
-msgid "### Type definitions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1029
-msgid ""
-"A _type definition_ defines a new name for an existing [type](#types). Type "
-"definitions are declared with the keyword `type`. Every value has a single, "
-"specific type; the type-specified aspects of a value include:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1035
-msgid "Whether the value is composed of sub-values or is indivisible."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1035
-msgid "Whether the value represents textual or numerical information."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1035
-msgid "Whether the value represents integral or floating-point information."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1035
-msgid "The sequence of memory operations required to access the value."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1035
-msgid "The [kind](#type-kinds) of the type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1038
-msgid ""
-"For example, the type `(u8, u8)` defines the set of immutable values that "
-"are composite pairs, each containing two unsigned 8-bit integers accessed by "
-"pattern-matching and laid out in memory with the `x` component preceding the "
-"`y` component."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1040
-msgid "### Structures"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1042
-msgid ""
-"A _structure_ is a nominal [structure type](#structure-types) defined with "
-"the keyword `struct`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1044
-msgid "An example of a `struct` item and its use:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1050
-msgid ""
-"~~~~ struct Point {x: int, y: int} let p = Point {x: 10, y: 11}; let px: int "
-"= p.x; ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1053
-msgid ""
-"A _tuple structure_ is a nominal [tuple type](#tuple-types), also defined "
-"with the keyword `struct`.  For example:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1059
-msgid ""
-"~~~~ struct Point(int, int); let p = Point(10, 11); let px: int = match p "
-"{ Point(x, _) => x }; ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1063
-msgid ""
-"A _unit-like struct_ is a structure without any fields, defined by leaving "
-"off the list of fields entirely.  Such types will have a single value, just "
-"like the [unit value `()`](#unit-and-boolean-literals) of the unit type.  "
-"For example:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1068
-msgid "~~~~ struct Cookie; let c = [Cookie, Cookie, Cookie, Cookie]; ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1070
-msgid "### Enumerations"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1073
-msgid ""
-"An _enumeration_ is a simultaneous definition of a nominal [enumerated type]"
-"(#enumerated-types) as well as a set of *constructors*, that can be used to "
-"create or pattern-match values of the corresponding enumerated type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1075
-msgid "Enumerations are declared with the keyword `enum`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1077
-msgid "An example of an `enum` item and its use:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1083
-#, no-wrap
-msgid ""
-"~~~~\n"
-"enum Animal {\n"
-"  Dog,\n"
-"  Cat\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1087
-msgid "let mut a: Animal = Dog; a = Cat; ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1094
-#, no-wrap
-msgid ""
-"Enumeration constructors can have either named or unnamed fields:\n"
-"~~~~\n"
-"enum Animal {\n"
-"    Dog (~str, float),\n"
-"    Cat { name: ~str, weight: float }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1098
-msgid ""
-"let mut a: Animal = Dog(~\"Cocoa\", 37.2); a = Cat{ name: ~\"Spotty\", "
-"weight: 2.7 }; ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1101
-msgid ""
-"In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is "
-"simply called an enum variant."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1103
-msgid "### Static items"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1107
-msgid ""
-"~~~~~~~~ {.ebnf .gram} static_item : \"static\" ident ':' type '=' expr "
-"';' ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1114
-msgid ""
-"A *static item* is a named _constant value_ stored in the global data "
-"section of a crate.  Immutable static items are stored in the read-only data "
-"section.  The constant value bound to a static item is, like all constant "
-"values, evaluated at compile time.  Static items have the `static` lifetime, "
-"which outlives all other lifetimes in a Rust program.  Static items are "
-"declared with the `static` keyword.  A static item must have a _constant "
-"expression_ giving its definition."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1119
-msgid ""
-"Static items must be explicitly typed.  The type may be ```bool```, "
-"```char```, a number, or a type derived from those primitive types.  The "
-"derived types are borrowed pointers with the `'static` lifetime, fixed-size "
-"arrays, tuples, and structs."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1123
-msgid "~~~~ static BIT1: uint = 1 << 0; static BIT2: uint = 1 << 1;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1126
-msgid ""
-"static BITS: [uint, ..2] = [BIT1, BIT2]; static STRING: &'static str = "
-"\"bitstring\";"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1131
-#, no-wrap
-msgid ""
-"struct BitsNStrings<'self> {\n"
-"    mybits: [uint, ..2],\n"
-"    mystring: &'self str\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1137
-#, no-wrap
-msgid ""
-"static bits_n_strings: BitsNStrings<'static> = BitsNStrings {\n"
-"    mybits: BITS,\n"
-"    mystring: STRING\n"
-"};\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1139
-msgid "#### Mutable statics"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1147
-msgid ""
-"If a static item is declared with the ```mut``` keyword, then it is allowed "
-"to be modified by the program. One of Rust's goals is to make concurrency "
-"bugs hard to run into, and this is obviously a very large source of race "
-"conditions or other bugs. For this reason, an ```unsafe``` block is required "
-"when either reading or writing a mutable static variable. Care should be "
-"taken to ensure that modifications to a mutable static are safe with respect "
-"to other tasks running in the same process."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1150
-msgid ""
-"Mutable statics are still very useful, however. They can be used with C "
-"libraries and can also be bound from C libraries (in an ```extern``` block)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1153
-msgid "~~~ # fn atomic_add(_: &mut uint, _: uint) -> uint { 2 }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1155
-msgid "static mut LEVELS: uint = 0;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1163
-#, no-wrap
-msgid ""
-"// This violates the idea of no shared state, and this doesn't internally\n"
-"// protect against races, so this function is `unsafe`\n"
-"unsafe fn bump_levels_unsafe1() -> uint {\n"
-"    let ret = LEVELS;\n"
-"    LEVELS += 1;\n"
-"    return ret;\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1170
-#, no-wrap
-msgid ""
-"// Assuming that we have an atomic_add function which returns the old value,\n"
-"// this function is \"safe\" but the meaning of the return value may not be what\n"
-"// callers expect, so it's still marked as `unsafe`\n"
-"unsafe fn bump_levels_unsafe2() -> uint {\n"
-"    return atomic_add(&mut LEVELS, 1);\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1172
-msgid "~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1174
-msgid "### Traits"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1176
-msgid "A _trait_ describes a set of method types."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1181
-msgid ""
-"Traits can include default implementations of methods, written in terms of "
-"some unknown [`self` type](#self-types); the `self` type may either be "
-"completely unspecified, or constrained by some other trait."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1183
-msgid ""
-"Traits are implemented for specific types through separate [implementations]"
-"(#implementations)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1187
-msgid "~~~~ # type Surface = int; # type BoundingBox = int;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1193
-#, no-wrap
-msgid ""
-"trait Shape {\n"
-"    fn draw(&self, Surface);\n"
-"    fn bounding_box(&self) -> BoundingBox;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1197
-msgid ""
-"This defines a trait with two methods.  All values that have "
-"[implementations](#implementations) of this trait in scope can have their "
-"`draw` and `bounding_box` methods called, using `value.bounding_box()` "
-"[syntax](#method-call-expressions)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1200
-msgid ""
-"Type parameters can be specified for a trait to make it generic.  These "
-"appear after the trait name, using the same syntax used in [generic "
-"functions](#generic-functions)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1208
-#, no-wrap
-msgid ""
-"~~~~\n"
-"trait Seq<T> {\n"
-"   fn len(&self) -> uint;\n"
-"   fn elt_at(&self, n: uint) -> T;\n"
-"   fn iter(&self, |T|);\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1214
-msgid ""
-"Generic functions may use traits as _bounds_ on their type parameters.  This "
-"will have two effects: only types that have the trait may instantiate the "
-"parameter, and within the generic function, the methods of the trait can be "
-"called on values that have the parameter's type.  For example:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1218
-msgid "~~~~ # type Surface = int; # trait Shape { fn draw(&self, Surface); }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1224
-#, no-wrap
-msgid ""
-"fn draw_twice<T: Shape>(surface: Surface, sh: T) {\n"
-"    sh.draw(surface);\n"
-"    sh.draw(surface);\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1229
-msgid ""
-"Traits also define an [object type](#object-types) with the same name as the "
-"trait.  Values of this type are created by [casting](#type-cast-expressions) "
-"pointer values (pointing to a type for which an implementation of the given "
-"trait is in scope)  to pointers to the trait name, used as a type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1234
-msgid "~~~~ # trait Shape { } # impl Shape for int { } # let mycircle = 0;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1237
-msgid "let myshape: @Shape = @mycircle as @Shape; ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1243
-msgid ""
-"The resulting value is a managed box containing the value that was cast, "
-"along with information that identifies the methods of the implementation "
-"that was used.  Values with a trait type can have [methods called](#method-"
-"call-expressions) on them, for any method in the trait, and can be used to "
-"instantiate type parameters that are bounded by the trait."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1251
-msgid ""
-"Trait methods may be static, which means that they lack a `self` argument.  "
-"This means that they can only be called with function call syntax (`f(x)`)  "
-"and not method call syntax (`obj.f()`).  The way to refer to the name of a "
-"static method is to qualify it with the trait name, treating the trait name "
-"like a module.  For example:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1261
-#, no-wrap
-msgid ""
-"~~~~\n"
-"trait Num {\n"
-"    fn from_int(n: int) -> Self;\n"
-"}\n"
-"impl Num for float {\n"
-"    fn from_int(n: int) -> float { n as float }\n"
-"}\n"
-"let x: float = Num::from_int(42);\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1263
-msgid "Traits may inherit from other traits. For example, in"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1268
-msgid ""
-"~~~~ trait Shape { fn area() -> float; } trait Circle : Shape { fn radius() -"
-"> float; } ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1273
-msgid ""
-"the syntax `Circle : Shape` means that types that implement `Circle` must "
-"also have an implementation for `Shape`.  Multiple supertraits are separated "
-"by spaces, `trait Circle : Shape Eq { }`.  In an implementation of `Circle` "
-"for a given type `T`, methods can refer to `Shape` methods, since the "
-"typechecker checks that any type with an implementation of `Circle` also has "
-"an implementation of `Shape`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1277 doc/tutorial.md:2176
-msgid ""
-"In type-parameterized functions, methods of the supertrait may be called on "
-"values of subtrait-bound type parameters.  Refering to the previous example "
-"of `trait Circle : Shape`:"
-msgstr ""
-"型パラメータを持つ関数では、サブトレイトの境界型パラメータの値によりスーパー"
-"トレイトのメソッドを呼び出すことになります。前の例の `trait Circle : Shape` "
-"を参照してください。"
-
-#. type: Plain text
-#: doc/rust.md:1286 doc/tutorial.md:2185
-#, no-wrap
-msgid ""
-"~~~\n"
-"# trait Shape { fn area(&self) -> float; }\n"
-"# trait Circle : Shape { fn radius(&self) -> float; }\n"
-"fn radius_times_area<T: Circle>(c: T) -> float {\n"
-"    // `c` is both a Circle and a Shape\n"
-"    c.radius() * c.area()\n"
-"}\n"
-"~~~\n"
-msgstr ""
-"~~~\n"
-"# trait Shape { fn area(&self) -> float; }\n"
-"# trait Circle : Shape { fn radius(&self) -> float; }\n"
-"fn radius_times_area<T: Circle>(c: T) -> float {\n"
-"    // `c` は Circle でもあり、Shape でもある\n"
-"    c.radius() * c.area()\n"
-"}\n"
-"~~~\n"
-
-#. type: Plain text
-#: doc/rust.md:1288 doc/tutorial.md:2187
-msgid "Likewise, supertrait methods may also be called on trait objects."
-msgstr ""
-"同様に、スーパートレイトのメソッドは、トレイトオブジェクトについても呼び出す"
-"ことが可能です。"
-
-#. type: Plain text
-#: doc/rust.md:1295
-msgid ""
-"~~~ {.xfail-test} # trait Shape { fn area(&self) -> float; } # trait "
-"Circle : Shape { fn radius(&self) -> float; } # impl Shape for int { fn "
-"area(&self) -> float { 0.0 } } # impl Circle for int { fn radius(&self) -> "
-"float { 0.0 } } # let mycircle = 0;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1299
-msgid ""
-"let mycircle: Circle = @mycircle as @Circle; let nonsense = mycircle."
-"radius() * mycircle.area(); ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1301
-msgid "### Implementations"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1303
-msgid ""
-"An _implementation_ is an item that implements a [trait](#traits) for a "
-"specific type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1305
-msgid "Implementations are defined with the keyword `impl`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1312
-msgid ""
-"~~~~ # struct Point {x: float, y: float}; # type Surface = int; # struct "
-"BoundingBox {x: float, y: float, width: float, height: float}; # trait Shape "
-"{ fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; } # fn "
-"do_draw_circle(s: Surface, c: Circle) { }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1317
-#, no-wrap
-msgid ""
-"struct Circle {\n"
-"    radius: float,\n"
-"    center: Point,\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1327
-#, no-wrap
-msgid ""
-"impl Shape for Circle {\n"
-"    fn draw(&self, s: Surface) { do_draw_circle(s, *self); }\n"
-"    fn bounding_box(&self) -> BoundingBox {\n"
-"        let r = self.radius;\n"
-"        BoundingBox{x: self.center.x - r, y: self.center.y - r,\n"
-"         width: 2.0 * r, height: 2.0 * r}\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1334
-msgid ""
-"It is possible to define an implementation without referring to a trait.  "
-"The methods in such an implementation can only be used as direct calls on "
-"the values of the type that the implementation targets.  In such an "
-"implementation, the trait type and `for` after `impl` are omitted.  Such "
-"implementations are limited to nominal types (enums, structs), and the "
-"implementation must appear in the same module or a sub-module as the `self` "
-"type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1338
-msgid ""
-"When a trait _is_ specified in an `impl`, all methods declared as part of "
-"the trait must be implemented, with matching types and type parameter counts."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1342
-msgid ""
-"An implementation can take type parameters, which can be different from the "
-"type parameters taken by the trait it implements.  Implementation parameters "
-"are written after the `impl` keyword."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1345
-msgid "~~~~ # trait Seq<T> { }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1353
-#, no-wrap
-msgid ""
-"impl<T> Seq<T> for ~[T] {\n"
-"   ...\n"
-"}\n"
-"impl Seq<bool> for u32 {\n"
-"   /* Treat the integer as a sequence of bits */\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1355
-msgid "### External blocks"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1360
-msgid ""
-"~~~ {.ebnf .gram} extern_block_item : \"extern\" '{' extern_block '} ; "
-"extern_block : [ foreign_fn ] * ; ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1364
-msgid ""
-"External blocks form the basis for Rust's foreign function interface.  "
-"Declarations in an external block describe symbols in external, non-Rust "
-"libraries."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1369
-msgid ""
-"Functions within external blocks are declared in the same way as other Rust "
-"functions, with the exception that they may not have a body and are instead "
-"terminated by a semicolon."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1373
-msgid "~~~ # use std::libc::{c_char, FILE}; # #[nolink]"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1378
-#, no-wrap
-msgid ""
-"extern {\n"
-"    fn fopen(filename: *c_char, mode: *c_char) -> *FILE;\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1383
-msgid ""
-"Functions within external blocks may be called by Rust code, just like "
-"functions defined in Rust.  The Rust compiler automatically translates "
-"between the Rust ABI and the foreign ABI."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1386
-msgid ""
-"A number of [attributes](#attributes) control the behavior of external "
-"blocks."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1390
-msgid ""
-"By default external blocks assume that the library they are calling uses the "
-"standard C \"cdecl\" ABI.  Other ABIs may be specified using the `abi` "
-"attribute as in"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1396
-msgid ""
-"~~~{.xfail-test} // Interface to the Windows API #[abi = \"stdcall\"] extern "
-"{ } ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1398
-msgid ""
-"The `link_name` attribute allows the name of the library to be specified."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1403
-msgid "~~~{.xfail-test} #[link_name = \"crypto\"] extern { } ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1409
-msgid ""
-"The `nolink` attribute tells the Rust compiler not to do any linking for the "
-"external block.  This is particularly useful for creating external blocks "
-"for libc, which tends to not follow standard library naming conventions and "
-"is linked to all Rust programs anyway."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1411
-msgid "## Attributes"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1418
-#, no-wrap
-msgid ""
-"~~~~~~~~{.ebnf .gram}\n"
-"attribute : '#' '[' attr_list ']' ;\n"
-"attr_list : attr [ ',' attr_list ]*\n"
-"attr : ident [ '=' literal\n"
-"             | '(' attr_list ')' ] ? ;\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1424
-msgid ""
-"Static entities in Rust -- crates, modules and items -- may have "
-"_attributes_ applied to them. ^[Attributes in Rust are modeled on Attributes "
-"in ECMA-335, C#] An attribute is a general, free-form metadatum that is "
-"interpreted according to name, convention, and language and compiler "
-"version.  Attributes may appear as any of"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1428
-msgid "A single identifier, the attribute name"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1428
-msgid ""
-"An identifier followed by the equals sign '=' and a literal, providing a key/"
-"value pair"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1428
-msgid ""
-"An identifier followed by a parenthesized list of sub-attribute arguments"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1431
-msgid ""
-"Attributes terminated by a semi-colon apply to the entity that the attribute "
-"is declared within. Attributes that are not terminated by a semi-colon apply "
-"to the next entity."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1433
-msgid "An example of attributes:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1437
-msgid ""
-"~~~~~~~~{.xfail-test} // General metadata applied to the enclosing module or "
-"crate.  #[license = \"BSD\"];"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1443
-#, no-wrap
-msgid ""
-"// A function marked as a unit test\n"
-"#[test]\n"
-"fn test_foo() {\n"
-"  ...\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1449
-#, no-wrap
-msgid ""
-"// A conditionally-compiled module\n"
-"#[cfg(target_os=\"linux\")]\n"
-"mod bar {\n"
-"  ...\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1454
-msgid ""
-"// A lint attribute used to suppress a warning/error "
-"#[allow(non_camel_case_types)] pub type int8_t = i8; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1457
-msgid ""
-"> **Note:** In future versions of Rust, user-provided extensions to the "
-"compiler will be able to interpret attributes.  > When this facility is "
-"provided, the compiler will distinguish between language-reserved and user-"
-"available attributes."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1460
-msgid ""
-"At present, only the Rust compiler interprets attributes, so all attribute "
-"names are effectively reserved. Some significant attributes include:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1471
-msgid "The `doc` attribute, for documenting code in-place."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1471
-msgid ""
-"The `cfg` attribute, for conditional-compilation by build-configuration."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1471
-msgid ""
-"The `lang` attribute, for custom definitions of traits and functions that "
-"are known to the Rust compiler (see [Language items](#language-items))."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1471
-msgid "The `link` attribute, for describing linkage metadata for a crate."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1471
-msgid "The `test` attribute, for marking functions as unit tests."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1471
-msgid ""
-"The `allow`, `warn`, `forbid`, and `deny` attributes, for controlling lint "
-"checks (see [Lint check attributes](#lint-check-attributes))."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1471
-msgid ""
-"The `deriving` attribute, for automatically generating implementations of "
-"certain traits."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1471
-msgid ""
-"The `static_assert` attribute, for asserting that a static bool is true at "
-"compiletime"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1473
-msgid ""
-"Other attributes may be added or removed during development of the language."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1475
-msgid "### Lint check attributes"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1479
-msgid ""
-"A lint check names a potentially undesirable coding pattern, such as "
-"unreachable code or omitted documentation, for the static entity to which "
-"the attribute applies."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1481
-msgid "For any lint check `C`:"
-msgstr ""
-
-#. type: Bullet: ' * '
-#: doc/rust.md:1488
-msgid "`warn(C)` warns about violations of `C` but continues compilation,"
-msgstr ""
-
-#. type: Bullet: ' * '
-#: doc/rust.md:1488
-msgid "`deny(C)` signals an error after encountering a violation of `C`,"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1488
-#, no-wrap
-msgid ""
-" * `allow(C)` overrides the check for `C` so that violations will go\n"
-"    unreported,\n"
-" * `forbid(C)` is the same as `deny(C)`, but also forbids uses of\n"
-"   `allow(C)` within the entity.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1491
-msgid ""
-"The lint checks supported by the compiler can be found via `rustc -W help`, "
-"along with their default settings."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1497
-#, no-wrap
-msgid ""
-"~~~{.xfail-test}\n"
-"mod m1 {\n"
-"    // Missing documentation is ignored here\n"
-"    #[allow(missing_doc)]\n"
-"    pub fn undocumented_one() -> int { 1 }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1501
-#, no-wrap
-msgid ""
-"    // Missing documentation signals a warning here\n"
-"    #[warn(missing_doc)]\n"
-"    pub fn undocumented_too() -> int { 2 }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1507
-#, no-wrap
-msgid ""
-"    // Missing documentation signals an error here\n"
-"    #[deny(missing_doc)]\n"
-"    pub fn undocumented_end() -> int { 3 }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1510
-msgid ""
-"This example shows how one can use `allow` and `warn` to toggle a particular "
-"check on and off."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1518
-#, no-wrap
-msgid ""
-"~~~{.xfail-test}\n"
-"#[warn(missing_doc)]\n"
-"mod m2{\n"
-"    #[allow(missing_doc)]\n"
-"    mod nested {\n"
-"        // Missing documentation is ignored here\n"
-"        pub fn undocumented_one() -> int { 1 }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1524
-#, no-wrap
-msgid ""
-"        // Missing documentation signals a warning here,\n"
-"        // despite the allow above.\n"
-"        #[warn(missing_doc)]\n"
-"        pub fn undocumented_two() -> int { 2 }\n"
-"    }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1529
-#, no-wrap
-msgid ""
-"    // Missing documentation signals a warning here\n"
-"    pub fn undocumented_too() -> int { 3 }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1532
-msgid ""
-"This example shows how one can use `forbid` to disallow uses of `allow` for "
-"that lint check."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1542
-#, no-wrap
-msgid ""
-"~~~{.xfail-test}\n"
-"#[forbid(missing_doc)]\n"
-"mod m3 {\n"
-"    // Attempting to toggle warning signals an error here\n"
-"    #[allow(missing_doc)]\n"
-"    /// Returns 2.\n"
-"    pub fn undocumented_too() -> int { 2 }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1544
-msgid "### Language items"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1550
-msgid ""
-"Some primitive Rust operations are defined in Rust code, rather than being "
-"implemented directly in C or assembly language.  The definitions of these "
-"operations have to be easy for the compiler to find.  The `lang` attribute "
-"makes it possible to declare these operations.  For example, the `str` "
-"module in the Rust standard library defines the string equality function:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1557
-#, no-wrap
-msgid ""
-"~~~ {.xfail-test}\n"
-"#[lang=\"str_eq\"]\n"
-"pub fn eq_slice(a: &str, b: &str) -> bool {\n"
-"    // details elided\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1561
-msgid ""
-"The name `str_eq` has a special meaning to the Rust compiler, and the "
-"presence of this definition means that it will use this definition when "
-"generating calls to the string equality function."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1563
-msgid "A complete list of the built-in language items follows:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1565
-msgid "#### Traits"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1604
-#, no-wrap
-msgid ""
-"`const`\n"
-"  : Cannot be mutated.\n"
-"`owned`\n"
-"  : Are uniquely owned.\n"
-"`durable`\n"
-"  : Contain borrowed pointers.\n"
-"`drop`\n"
-"  : Have finalizers.\n"
-"`add`\n"
-"  : Elements can be added (for example, integers and floats).\n"
-"`sub`\n"
-"  : Elements can be subtracted.\n"
-"`mul`\n"
-"  : Elements can be multiplied.\n"
-"`div`\n"
-"  : Elements have a division operation.\n"
-"`rem`\n"
-"  : Elements have a remainder operation.\n"
-"`neg`\n"
-"  : Elements can be negated arithmetically.\n"
-"`not`\n"
-"  : Elements can be negated logically.\n"
-"`bitxor`\n"
-"  : Elements have an exclusive-or operation.\n"
-"`bitand`\n"
-"  : Elements have a bitwise `and` operation.\n"
-"`bitor`\n"
-"  : Elements have a bitwise `or` operation.\n"
-"`shl`\n"
-"  : Elements have a left shift operation.\n"
-"`shr`\n"
-"  : Elements have a right shift operation.\n"
-"`index`\n"
-"  : Elements can be indexed.\n"
-"`eq`\n"
-"  : Elements can be compared for equality.\n"
-"`ord`\n"
-"  : Elements have a partial ordering.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1606
-msgid "#### Operations"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1636
-#, no-wrap
-msgid ""
-"`str_eq`\n"
-"  : Compare two strings for equality.\n"
-"`uniq_str_eq`\n"
-"  : Compare two owned strings for equality.\n"
-"`annihilate`\n"
-"  : Destroy a box before freeing it.\n"
-"`log_type`\n"
-"  : Generically print a string representation of any type.\n"
-"`fail_`\n"
-"  : Abort the program with an error.\n"
-"`fail_bounds_check`\n"
-"  : Abort the program with a bounds check error.\n"
-"`exchange_malloc`\n"
-"  : Allocate memory on the exchange heap.\n"
-"`exchange_free`\n"
-"  : Free memory that was allocated on the exchange heap.\n"
-"`malloc`\n"
-"  : Allocate memory on the managed heap.\n"
-"`free`\n"
-"  : Free memory that was allocated on the managed heap.\n"
-"`borrow_as_imm`\n"
-"  : Create an immutable borrowed pointer to a mutable value.\n"
-"`return_to_mut`\n"
-"  : Release a borrowed pointer created with `return_to_mut`\n"
-"`check_not_borrowed`\n"
-"  : Fail if a value has existing borrowed pointers to it.\n"
-"`strdup_uniq`\n"
-"  : Return a new unique string\n"
-"    containing a copy of the contents of a unique string.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1639
-msgid ""
-"> **Note:** This list is likely to become out of date. We should auto-"
-"generate it > from `librustc/middle/lang_items.rs`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1641
-msgid "### Deriving"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1647
-msgid ""
-"The `deriving` attribute allows certain traits to be automatically "
-"implemented for data structures. For example, the following will create an "
-"`impl` for the `Eq` and `Clone` traits for `Foo`, the type parameter `T` "
-"will be given the `Eq` or `Clone` constraints for the appropriate `impl`:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1655
-#, no-wrap
-msgid ""
-"~~~\n"
-"#[deriving(Eq, Clone)]\n"
-"struct Foo<T> {\n"
-"    a: int,\n"
-"    b: T\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1657
-msgid "The generated `impl` for `Eq` is equivalent to"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1664
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Foo<T> { a: int, b: T }\n"
-"impl<T: Eq> Eq for Foo<T> {\n"
-"    fn eq(&self, other: &Foo<T>) -> bool {\n"
-"        self.a == other.a && self.b == other.b\n"
-"    }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1670
-#, no-wrap
-msgid ""
-"    fn ne(&self, other: &Foo<T>) -> bool {\n"
-"        self.a != other.a || self.b != other.b\n"
-"    }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1672
-msgid "Supported traits for `deriving` are:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1683
-msgid "Comparison traits: `Eq`, `TotalEq`, `Ord`, `TotalOrd`."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1683
-msgid "Serialization: `Encodable`, `Decodable`. These require `extra`."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1683
-msgid "`Clone` and `DeepClone`, to perform (deep) copies."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1683
-msgid "`IterBytes`, to iterate over the bytes in a data type."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1683
-msgid "`Rand`, to create a random instance of a data type."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1683
-msgid "`Zero`, to create an zero (or empty) instance of a data type."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:1683
-msgid ""
-"`ToStr`, to convert to a string. For a type with this instance, `obj."
-"to_str()` has similar output as `fmt!(\"%?\", obj)`, but it differs in that "
-"each constituent field of the type must also implement `ToStr` and will have "
-"`field.to_str()` invoked to build up the result."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1685
-msgid "# Statements and expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1692
-msgid ""
-"Rust is _primarily_ an expression language. This means that most forms of "
-"value-producing or effect-causing evaluation are directed by the uniform "
-"syntax category of _expressions_. Each kind of expression can typically "
-"_nest_ within each other kind of expression, and rules for evaluation of "
-"expressions involve specifying both the value produced by the expression and "
-"the order in which its sub-expressions are themselves evaluated."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1695
-msgid ""
-"In contrast, statements in Rust serve _mostly_ to contain and explicitly "
-"sequence expression evaluation."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1697
-msgid "## Statements"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1700
-msgid ""
-"A _statement_ is a component of a block, which is in turn a component of an "
-"outer [expression](#expressions) or [function](#functions)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1704
-msgid ""
-"Rust has two kinds of statement: [declaration statements](#declaration-"
-"statements) and [expression statements](#expression-statements)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1706
-msgid "### Declaration statements"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1709
-msgid ""
-"A _declaration statement_ is one that introduces one or more *names* into "
-"the enclosing statement block.  The declared names may denote new slots or "
-"new items."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1711
-msgid "#### Item declarations"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1718
-msgid ""
-"An _item declaration statement_ has a syntactic form identical to an [item]"
-"(#items) declaration within a module. Declaring an item -- a function, "
-"enumeration, structure, type, static, trait, implementation or module -- "
-"locally within a statement block is simply a way of restricting its scope to "
-"a narrow region containing all of its uses; it is otherwise identical in "
-"meaning to declaring the item outside the statement block."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1721
-msgid ""
-"Note: there is no implicit capture of the function's dynamic environment "
-"when declaring a function-local item."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1724
-msgid "#### Slot declarations"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1729
-msgid ""
-"~~~~~~~~{.ebnf .gram} let_decl : \"let\" pat [':' type ] ? [ init ] ? ';' ; "
-"init : [ '=' ] expr ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1735
-msgid ""
-"A _slot declaration_ introduces a new set of slots, given by a pattern.  The "
-"pattern may be followed by a type annotation, and/or an initializer "
-"expression.  When no type annotation is given, the compiler will infer the "
-"type, or signal an error if insufficient type information is available for "
-"definite inference.  Any slots introduced by a slot declaration are visible "
-"from the point of declaration until the end of the enclosing block scope."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1737
-msgid "### Expression statements"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1742
-msgid ""
-"An _expression statement_ is one that evaluates an [expression]"
-"(#expressions)  and ignores its result.  The type of an expression statement "
-"`e;` is always `()`, regardless of the type of `e`.  As a rule, an "
-"expression statement's purpose is to trigger the effects of evaluating its "
-"expression."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1744
-msgid "## Expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1753
-#, no-wrap
-msgid ""
-"An expression may have two roles: it always produces a *value*, and it may have *effects*\n"
-"(otherwise known as \"side effects\").\n"
-"An expression *evaluates to* a value, and has effects during *evaluation*.\n"
-"Many expressions contain sub-expressions (operands).\n"
-"The meaning of each kind of expression dictates several things:\n"
-"  * Whether or not to evaluate the sub-expressions when evaluating the expression\n"
-"  * The order in which to evaluate the sub-expressions\n"
-"  * How to combine the sub-expressions' values to obtain the value of the expression.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1758
-msgid ""
-"In this way, the structure of expressions dictates the structure of "
-"execution.  Blocks are just another kind of expression, so blocks, "
-"statements, expressions, and blocks again can recursively nest inside each "
-"other to an arbitrary depth."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1760
-msgid "#### Lvalues, rvalues and temporaries"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1764
-msgid ""
-"Expressions are divided into two main categories: _lvalues_ and _rvalues_.  "
-"Likewise within each expression, sub-expressions may occur in _lvalue "
-"context_ or _rvalue context_.  The evaluation of an expression depends both "
-"on its own category and the context it occurs within."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1767
-msgid ""
-"[Path](#path-expressions), [field](#field-expressions) and [index](#index-"
-"expressions) expressions are lvalues.  All other expressions are rvalues."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1775
-msgid ""
-"The left operand of an [assignment](#assignment-expressions), [binary move]"
-"(#binary-move-expressions) or [compound-assignment](#compound-assignment-"
-"expressions) expression is an lvalue context, as is the single operand of a "
-"unary [borrow](#unary-operator-expressions), or [move](#unary-move-"
-"expressions) expression, and _both_ operands of a [swap](#swap-expressions) "
-"expression.  All other expression contexts are rvalue contexts."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1778
-msgid ""
-"When an lvalue is evaluated in an _lvalue context_, it denotes a memory "
-"location; when evaluated in an _rvalue context_, it denotes the value held "
-"_in_ that memory location."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1781
-msgid ""
-"When an rvalue is used in lvalue context, a temporary un-named lvalue is "
-"created and used instead.  A temporary's lifetime equals the largest "
-"lifetime of any borrowed pointer that points to it."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1783
-msgid "#### Moved and copied types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1792
-msgid ""
-"When a [local variable](#memory-slots) is used as an [rvalue](#lvalues-"
-"rvalues-and-temporaries)  the variable will either be [moved](#move-"
-"expressions) or copied, depending on its type.  For types that contain "
-"[owning pointers](#owning-pointers)  or values that implement the special "
-"trait `Drop`, the variable is moved.  All other types are copied."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1795
-msgid "### Literal expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1799
-msgid ""
-"A _literal expression_ consists of one of the [literal](#literals)  forms "
-"described earlier. It directly describes a number, character, string, "
-"boolean value, or the unit value."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1806
-#, no-wrap
-msgid ""
-"~~~~~~~~ {.literals}\n"
-"();        // unit type\n"
-"\"hello\";   // string type\n"
-"'5';       // character type\n"
-"5;         // integer type\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1808
-msgid "### Path expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1811
-msgid ""
-"A [path](#paths) used as an expression context denotes either a local "
-"variable or an item.  Path expressions are [lvalues](#lvalues-rvalues-and-"
-"temporaries)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1813
-msgid "### Tuple expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1817
-msgid ""
-"Tuples are written by enclosing one or more comma-separated expressions in "
-"parentheses. They are used to create [tuple-typed](#tuple-types)  values."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1823
-msgid "~~~~~~~~ {.tuple} (0,); (0f, 4.5f); (\"a\", 4u, true); ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1825
-msgid "### Structure expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1834
-#, no-wrap
-msgid ""
-"~~~~~~~~{.ebnf .gram}\n"
-"struct_expr : expr_path '{' ident ':' expr\n"
-"                      [ ',' ident ':' expr ] *\n"
-"                      [ \"..\" expr ] '}' |\n"
-"              expr_path '(' expr\n"
-"                      [ ',' expr ] * ')' |\n"
-"              expr_path\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1841
-msgid ""
-"There are several forms of structure expressions.  A _structure expression_ "
-"consists of the [path](#paths) of a [structure item](#structures), followed "
-"by a brace-enclosed list of one or more comma-separated name-value pairs, "
-"providing the field values of a new instance of the structure.  A field name "
-"can be any identifier, and is separated from its value expression by a "
-"colon.  The location denoted by a structure field is mutable if and only if "
-"the enclosing structure is mutable."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1846
-msgid ""
-"A _tuple structure expression_ consists of the [path](#paths) of a "
-"[structure item](#structures), followed by a parenthesized list of one or "
-"more comma-separated expressions (in other words, the path of a structure "
-"item followed by a tuple expression).  The structure item must be a tuple "
-"structure item."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1848
-msgid ""
-"A _unit-like structure expression_ consists only of the [path](#paths) of a "
-"[structure item](#structures)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1850
-msgid "The following are examples of structure expressions:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1861
-msgid ""
-"~~~~ # struct Point { x: float, y: float } # struct TuplePoint(float, "
-"float); # mod game { pub struct User<'self> { name: &'self str, age: uint, "
-"score: uint } } # struct Cookie; fn some_fn<T>(t: T) {} Point {x: 10f, y: "
-"20f}; TuplePoint(10f, 20f); let u = game::User {name: \"Joe\", age: 35, "
-"score: 100_000}; some_fn::<Cookie>(Cookie); ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1864
-msgid ""
-"A structure expression forms a new value of the named structure type.  Note "
-"that for a given *unit-like* structure type, this will always be the same "
-"value."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1871
-msgid ""
-"A structure expression can terminate with the syntax `..` followed by an "
-"expression to denote a functional update.  The expression following `..` "
-"(the base) must have the same structure type as the new structure type being "
-"formed.  The entire expression denotes the result of allocating a new "
-"structure (with the same type as the base expression)  with the given values "
-"for the fields that were explicitly specified and the values in the base "
-"record for all other fields."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1877
-msgid ""
-"~~~~ # struct Point3d { x: int, y: int, z: int } let base = Point3d {x: 1, "
-"y: 2, z: 3}; Point3d {y: 0, z: 10, .. base}; ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1879
-msgid "### Record expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1885
-#, no-wrap
-msgid ""
-"~~~~~~~~{.ebnf .gram}\n"
-"rec_expr : '{' ident ':' expr\n"
-"               [ ',' ident ':' expr ] *\n"
-"               [ \"..\" expr ] '}'\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1887
-msgid "### Method-call expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1891
-msgid ""
-"~~~~~~~~{.ebnf .gram} method_call_expr : expr '.' ident paren_expr_list ; "
-"~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1896
-msgid ""
-"A _method call_ consists of an expression followed by a single dot, an "
-"identifier, and a parenthesized expression-list.  Method calls are resolved "
-"to methods on specific traits, either statically dispatching to a method if "
-"the exact `self`-type of the left-hand-side is known, or dynamically "
-"dispatching if the left-hand-side expression is an indirect [object type]"
-"(#object-types)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1899
-msgid "### Field expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1903
-msgid "~~~~~~~~{.ebnf .gram} field_expr : expr '.' ident ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1907
-msgid ""
-"A _field expression_ consists of an expression followed by a single dot and "
-"an identifier, when not immediately followed by a parenthesized expression-"
-"list (the latter is a [method call expression](#method-call-expressions)).  "
-"A field expression denotes a field of a [structure](#structure-types)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1912
-msgid "~~~~~~~~ {.field} myrecord.myfield; {a: 10, b: 20}.a; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1915
-msgid ""
-"A field access on a record is an [lvalue](#lvalues-rvalues-and-temporaries) "
-"referring to the value of that field.  When the field is mutable, it can be "
-"[assigned](#assignment-expressions) to."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1918
-msgid ""
-"When the type of the expression to the left of the dot is a pointer to a "
-"record or structure, it is automatically derferenced to make the field "
-"access possible."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1921
-msgid "### Vector expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1924
-msgid "~~~~~~~~{.ebnf .gram} vec_expr : '[' \"mut\"? vec_elems? ']'"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1927
-msgid "vec_elems : [expr [',' expr]*] | [expr ',' \"..\" expr] ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1930
-msgid ""
-"A [_vector_](#vector-types) _expression_ is written by enclosing zero or "
-"more comma-separated expressions of uniform type in square brackets."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1934
-msgid ""
-"In the `[expr ',' \"..\" expr]` form, the expression after the `\"..\"` must "
-"be a constant expression that can be evaluated at compile time, such as a "
-"[literal](#literals) or a [static item](#static-items)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1941
-#, no-wrap
-msgid ""
-"~~~~\n"
-"[1, 2, 3, 4];\n"
-"[\"a\", \"b\", \"c\", \"d\"];\n"
-"[0, ..128];             // vector with 128 zeros\n"
-"[0u8, 0u8, 0u8, 0u8];\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1943
-msgid "### Index expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1947
-msgid "~~~~~~~~{.ebnf .gram} idx_expr : expr '[' expr ']' ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1952
-msgid ""
-"[Vector](#vector-types)-typed expressions can be indexed by writing a square-"
-"bracket-enclosed expression (the index) after them. When the vector is "
-"mutable, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can be "
-"assigned to."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1956
-msgid ""
-"Indices are zero-based, and may be of any integral type. Vector access is "
-"bounds-checked at run-time. When the check fails, it will put the task in a "
-"_failing state_."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1960
-msgid "~~~~ # use std::task; # do task::spawn_unlinked {"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1963
-msgid "([1, 2, 3, 4])[0]; ([\"a\", \"b\"])[10]; // fails"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1966 doc/tutorial-tasks.md:648
-msgid "# } ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1968
-msgid "### Unary operator expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1972
-msgid ""
-"Rust defines six symbolic unary operators.  They are all written as prefix "
-"operators, before the expression they apply to."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1991
-#, no-wrap
-msgid ""
-"`-`\n"
-"  : Negation. May only be applied to numeric types.\n"
-"`*`\n"
-"  : Dereference. When applied to a [pointer](#pointer-types) it denotes the pointed-to location.\n"
-"    For pointers to mutable locations, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to.\n"
-"    For [enums](#enumerated-types) that have only a single variant, containing a single parameter,\n"
-"    the dereference operator accesses this parameter.\n"
-"`!`\n"
-"  : Logical negation. On the boolean type, this flips between `true` and\n"
-"    `false`. On integer types, this inverts the individual bits in the\n"
-"    two's complement representation of the value.\n"
-"`@` and `~`\n"
-"  :  [Boxing](#pointer-types) operators. Allocate a box to hold the value they are applied to,\n"
-"     and store the value in it. `@` creates a managed box, whereas `~` creates an owned box.\n"
-"`&`\n"
-"  : Borrow operator. Returns a borrowed pointer, pointing to its operand.\n"
-"    The operand of a borrowed pointer is statically proven to outlive the resulting pointer.\n"
-"    If the borrow-checker cannot prove this, it is a compilation error.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1993
-msgid "### Binary operator expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:1997
-msgid "~~~~~~~~{.ebnf .gram} binop_expr : expr binop expr ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2000
-msgid ""
-"Binary operators expressions are given in terms of [operator precedence]"
-"(#operator-precedence)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2002
-msgid "#### Arithmetic operators"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2007
-msgid ""
-"Binary arithmetic expressions are syntactic sugar for calls to built-in "
-"traits, defined in the `std::ops` module of the `std` library.  This means "
-"that arithmetic operators can be overridden for user-defined types.  The "
-"default meaning of the operators on standard types is given here."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2023
-#, no-wrap
-msgid ""
-"`+`\n"
-"  : Addition and vector/string concatenation.\n"
-"    Calls the `add` method on the `std::ops::Add` trait.\n"
-"`-`\n"
-"  : Subtraction.\n"
-"    Calls the `sub` method on the `std::ops::Sub` trait.\n"
-"`*`\n"
-"  : Multiplication.\n"
-"    Calls the `mul` method on the `std::ops::Mul` trait.\n"
-"`/`\n"
-"  : Quotient.\n"
-"    Calls the `div` method on the `std::ops::Div` trait.\n"
-"`%`\n"
-"  : Remainder.\n"
-"    Calls the `rem` method on the `std::ops::Rem` trait.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2025
-msgid "#### Bitwise operators"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2030
-msgid ""
-"Like the [arithmetic operators](#arithmetic-operators), bitwise operators "
-"are syntactic sugar for calls to methods of built-in traits.  This means "
-"that bitwise operators can be overridden for user-defined types.  The "
-"default meaning of the operators on standard types is given here."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2046
-#, no-wrap
-msgid ""
-"`&`\n"
-"  : And.\n"
-"    Calls the `bitand` method of the `std::ops::BitAnd` trait.\n"
-"`|`\n"
-"  : Inclusive or.\n"
-"    Calls the `bitor` method of the `std::ops::BitOr` trait.\n"
-"`^`\n"
-"  : Exclusive or.\n"
-"    Calls the `bitxor` method of the `std::ops::BitXor` trait.\n"
-"`<<`\n"
-"  : Logical left shift.\n"
-"    Calls the `shl` method of the `std::ops::Shl` trait.\n"
-"`>>`\n"
-"  : Logical right shift.\n"
-"    Calls the `shr` method of the `std::ops::Shr` trait.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2048
-msgid "#### Lazy boolean operators"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2055
-msgid ""
-"The operators `||` and `&&` may be applied to operands of boolean type.  The "
-"`||` operator denotes logical 'or', and the `&&` operator denotes logical "
-"'and'.  They differ from `|` and `&` in that the right-hand operand is only "
-"evaluated when the left-hand operand does not already determine the result "
-"of the expression.  That is, `||` only evaluates its right-hand operand when "
-"the left-hand operand evaluates to `false`, and `&&` only when it evaluates "
-"to `true`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2057
-msgid "#### Comparison operators"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2063
-msgid ""
-"Comparison operators are, like the [arithmetic operators](#arithmetic-"
-"operators), and [bitwise operators](#bitwise-operators), syntactic sugar for "
-"calls to built-in traits.  This means that comparison operators can be "
-"overridden for user-defined types.  The default meaning of the operators on "
-"standard types is given here."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2082
-#, no-wrap
-msgid ""
-"`==`\n"
-"  : Equal to.\n"
-"    Calls the `eq` method on the `std::cmp::Eq` trait.\n"
-"`!=`\n"
-"  : Unequal to.\n"
-"    Calls the `ne` method on the `std::cmp::Eq` trait.\n"
-"`<`\n"
-"  : Less than.\n"
-"    Calls the `lt` method on the `std::cmp::Ord` trait.\n"
-"`>`\n"
-"  : Greater than.\n"
-"    Calls the `gt` method on the `std::cmp::Ord` trait.\n"
-"`<=`\n"
-"  : Less than or equal.\n"
-"    Calls the `le` method on the `std::cmp::Ord` trait.\n"
-"`>=`\n"
-"  : Greater than or equal.\n"
-"    Calls the `ge` method on the `std::cmp::Ord` trait.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2085
-msgid "#### Type cast expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2087
-msgid "A type cast expression is denoted with the binary operator `as`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2090
-msgid ""
-"Executing an `as` expression casts the value on the left-hand side to the "
-"type on the right-hand side."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2094
-msgid ""
-"A numeric value can be cast to any numeric type.  A raw pointer value can be "
-"cast to or from any integral type or raw pointer type.  Any other cast is "
-"unsupported and will fail to compile."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2096
-msgid "An example of an `as` expression:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2100
-msgid ""
-"~~~~ # fn sum(v: &[float]) -> float { 0.0 } # fn len(v: &[float]) -> int "
-"{ 0 }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2107
-#, no-wrap
-msgid ""
-"fn avg(v: &[float]) -> float {\n"
-"  let sum: float = sum(v);\n"
-"  let sz: float = len(v) as float;\n"
-"  return sum / sz;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2109
-msgid "#### Assignment expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2112
-msgid ""
-"An _assignment expression_ consists of an [lvalue](#lvalues-rvalues-and-"
-"temporaries) expression followed by an equals sign (`=`) and an [rvalue]"
-"(#lvalues-rvalues-and-temporaries) expression."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2114
-msgid ""
-"Evaluating an assignment expression [either copies or moves](#moved-and-"
-"copied-types) its right-hand operand to its left-hand operand."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2118
-msgid "~~~~ # let mut x = 0; # let y = 0;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2121
-msgid "x = y; ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2123
-msgid "#### Compound assignment expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2128
-msgid ""
-"The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be "
-"composed with the `=` operator. The expression `lval OP= val` is equivalent "
-"to `lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2130
-msgid "Any such expression always has the [`unit`](#primitive-types) type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2132
-msgid "#### Operator precedence"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2135
-msgid ""
-"The precedence of Rust binary operators is ordered as follows, going from "
-"strong to weak:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2148
-#, no-wrap
-msgid ""
-"~~~~ {.precedence}\n"
-"* / %\n"
-"as\n"
-"+ -\n"
-"<< >>\n"
-"&\n"
-"^\n"
-"|\n"
-"< > <= >=\n"
-"== !=\n"
-"&&\n"
-"||\n"
-"=\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2150 doc/rust.md:2237 doc/tutorial-macros.md:323
-msgid "~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2153
-msgid ""
-"Operators at the same precedence level are evaluated left-to-right. [Unary "
-"operators](#unary-operator-expressions)  have the same precedence level and "
-"it is stronger than any of the binary operators'."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2155
-msgid "### Grouped expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2159
-msgid ""
-"An expression enclosed in parentheses evaluates to the result of the "
-"enclosed expression.  Parentheses can be used to explicitly specify "
-"evaluation order within an expression."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2163
-msgid "~~~~~~~~{.ebnf .gram} paren_expr : '(' expr ')' ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2165
-msgid "An example of a parenthesized expression:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2169
-msgid "~~~~ let x = (2 + 3) * 4; ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2172
-msgid "### Call expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2178
-msgid ""
-"~~~~~~~~ {.abnf .gram} expr_list : [ expr [ ',' expr ]* ] ? ; "
-"paren_expr_list : '(' expr_list ')' ; call_expr : expr paren_expr_list ; "
-"~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2183
-msgid ""
-"A _call expression_ invokes a function, providing zero or more input slots "
-"and an optional reference slot to serve as the function's output, bound to "
-"the `lval` on the right hand side of the call. If the function eventually "
-"returns, then the expression completes."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2185
-msgid "Some examples of call expressions:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2189
-msgid ""
-"~~~~ # use std::from_str::FromStr; # fn add(x: int, y: int) -> int { 0 }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2193
-msgid ""
-"let x: int = add(1, 2); let pi = FromStr::from_str::<f32>(\"3.14\"); ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2195
-msgid "### Lambda expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2200
-msgid ""
-"~~~~~~~~ {.abnf .gram} ident_list : [ ident [ ',' ident ]* ] ? ; "
-"lambda_expr : '|' ident_list '|' expr ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2204
-msgid ""
-"A _lambda expression_ (sometimes called an \"anonymous function expression"
-"\") defines a function and denotes it as a value, in a single expression.  A "
-"lambda expression is a pipe-symbol-delimited (`|`) list of identifiers "
-"followed by an expression."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2209
-msgid ""
-"A lambda expression denotes a function that maps a list of parameters "
-"(`ident_list`)  onto the expression that follows the `ident_list`.  The "
-"identifiers in the `ident_list` are the parameters to the function.  These "
-"parameters' types need not be specified, as the compiler infers them from "
-"context."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2212
-msgid ""
-"Lambda expressions are most useful when passing functions as arguments to "
-"other functions, as an abbreviation for defining and capturing a separate "
-"function."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2221
-msgid ""
-"Significantly, lambda expressions _capture their environment_, which regular "
-"[function definitions](#functions) do not.  The exact type of capture "
-"depends on the [function type](#function-types) inferred for the lambda "
-"expression.  In the simplest and least-expensive form (analogous to a "
-"```|| { }``` expression), the lambda expression captures its environment "
-"by reference, effectively borrowing pointers to all outer variables "
-"mentioned inside the function.  Alternately, the compiler may infer that a "
-"lambda expression should copy or move values (depending on their type.)  "
-"from the environment into the lambda expression's captured environment."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2224
-msgid ""
-"In this example, we define a function `ten_times` that takes a higher-order "
-"function argument, and call it with a lambda expression as an argument."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2233
-#, no-wrap
-msgid ""
-"~~~~\n"
-"fn ten_times(f: |int|) {\n"
-"    let mut i = 0;\n"
-"    while i < 10 {\n"
-"        f(i);\n"
-"        i += 1;\n"
-"    }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2235
-msgid "ten_times(|j| println(fmt!(\"hello, %d\", j)));"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2239
-msgid "### While loops"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2243
-msgid ""
-"~~~~~~~~{.ebnf .gram} while_expr : \"while\" expr '{' block '}' ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2248
-msgid ""
-"A `while` loop begins by evaluating the boolean loop conditional "
-"expression.  If the loop conditional expression evaluates to `true`, the "
-"loop body block executes and control returns to the loop conditional "
-"expression. If the loop conditional expression evaluates to `false`, the "
-"`while` expression completes."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2250
-msgid "An example:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2253
-msgid "~~~~ let mut i = 0;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2259
-#, no-wrap
-msgid ""
-"while i < 10 {\n"
-"    println(\"hello\\n\");\n"
-"    i = i + 1;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2261
-msgid "### Infinite loops"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2265
-msgid ""
-"The keyword `loop` in Rust appears both in _loop expressions_ and in "
-"_continue expressions_.  A loop expression denotes an infinite loop; see "
-"[Continue expressions](#continue-expressions) for continue expressions."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2269
-msgid ""
-"~~~~~~~~{.ebnf .gram} loop_expr : [ lifetime ':' ] \"loop\" '{' block '}'; "
-"~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2274
-msgid ""
-"A `loop` expression may optionally have a _label_.  If a label is present, "
-"then labeled `break` and `loop` expressions nested within this loop may exit "
-"out of this loop or return control to its head.  See [Break expressions]"
-"(#break-expressions)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2276
-msgid "### Break expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2280
-msgid "~~~~~~~~{.ebnf .gram} break_expr : \"break\" [ lifetime ]; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2287
-msgid ""
-"A `break` expression has an optional `label`.  If the label is absent, then "
-"executing a `break` expression immediately terminates the innermost loop "
-"enclosing it.  It is only permitted in the body of a loop.  If the label is "
-"present, then `break foo` terminates the loop with label `foo`, which need "
-"not be the innermost label enclosing the `break` expression, but must "
-"enclose it."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2289
-msgid "### Continue expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2293
-msgid "~~~~~~~~{.ebnf .gram} continue_expr : \"loop\" [ lifetime ]; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2304
-msgid ""
-"A continue expression, written `loop`, also has an optional `label`.  If the "
-"label is absent, then executing a `loop` expression immediately terminates "
-"the current iteration of the innermost loop enclosing it, returning control "
-"to the loop *head*.  In the case of a `while` loop, the head is the "
-"conditional expression controlling the loop.  In the case of a `for` loop, "
-"the head is the call-expression controlling the loop.  If the label is "
-"present, then `loop foo` returns control to the head of the loop with label "
-"`foo`, which need not be the innermost label enclosing the `break` "
-"expression, but must enclose it."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2306
-msgid "A `loop` expression is only permitted in the body of a loop."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2309
-msgid "### Do expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2313
-msgid ""
-"~~~~~~~~{.ebnf .gram} do_expr : \"do\" expr [ '|' ident_list '|' ] ? '{' "
-"block '}' ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2316
-msgid ""
-"A _do expression_ provides a more-familiar block-syntax for a [lambda "
-"expression](#lambda-expressions), including a special translation of [return "
-"expressions](#return-expressions) inside the supplied block."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2324
-msgid ""
-"Any occurrence of a [return expression](#return-expressions)  inside this "
-"`block` expression is rewritten as a reference to an (anonymous) flag set in "
-"the caller's environment, which is checked on return from the `expr` and, if "
-"set, causes a corresponding return from the caller.  In this way, the "
-"meaning of `return` statements in language built-in control blocks is "
-"preserved, if they are rewritten using lambda functions and `do` expressions "
-"as abstractions."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2327
-msgid ""
-"The optional `ident_list` and `block` provided in a `do` expression are "
-"parsed as though they constitute a lambda expression; if the `ident_list` is "
-"missing, an empty `ident_list` is implied."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2333
-msgid ""
-"The lambda expression is then provided as a _trailing argument_ to the "
-"outermost [call](#call-expressions) or [method call](#method-call-"
-"expressions) expression in the `expr` following `do`.  If the `expr` is a "
-"[path expression](#path-expressions), it is parsed as though it is a call "
-"expression.  If the `expr` is a [field expression](#field-expressions), it "
-"is parsed as though it is a method call expression."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2335
-msgid "In this example, both calls to `f` are equivalent:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2339
-msgid "~~~~ # fn f(f: |int|) { } # fn g(i: int) { }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2341
-msgid "f(|j| g(j));"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2346
-#, no-wrap
-msgid ""
-"do f |j| {\n"
-"    g(j);\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2348
-msgid ""
-"In this example, both calls to the (binary) function `k` are equivalent:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2352
-msgid "~~~~ # fn k(x:int, f: |int|) { } # fn l(i: int) { }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2354
-msgid "k(3, |j| l(j));"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2359
-#, no-wrap
-msgid ""
-"do k(3) |j| {\n"
-"   l(j);\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2362
-msgid "### For expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2366
-msgid ""
-"~~~~~~~~{.ebnf .gram} for_expr : \"for\" expr [ '|' ident_list '|' ] ? '{' "
-"block '}' ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2370
-msgid ""
-"A _for expression_ is similar to a [`do` expression](#do-expressions), in "
-"that it provides a special block-form of lambda expression, suited to "
-"passing the `block` function to a higher-order function implementing a loop."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2376
-msgid ""
-"In contrast to a `do` expression, a `for` expression is designed to work "
-"with methods such as `each` and `times`, that require the body block to "
-"return a boolean. The `for` expression accommodates this by implicitly "
-"returning `true` at the end of each block, unless a `break` expression is "
-"evaluated."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2383
-msgid ""
-"In addition, [`break`](#break-expressions) and [`loop`](#loop-expressions) "
-"expressions are rewritten inside `for` expressions in the same way that "
-"`return` expressions are, with a combination of local flag variables, and "
-"early boolean-valued returns from the `block` function, such that the "
-"meaning of `break` and `loop` is preserved in a primitive loop when "
-"rewritten as a `for` loop controlled by a higher order function."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2385
-msgid "An example of a for loop over the contents of a vector:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2392
-msgid ""
-"~~~~ # type foo = int; # fn bar(f: foo) { } # let a = 0; # let b = 0; # let "
-"c = 0;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2394
-msgid "let v: &[foo] = &[a, b, c];"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2399
-#, no-wrap
-msgid ""
-"for e in v.iter() {\n"
-"    bar(*e);\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2401
-msgid "An example of a for loop over a series of integers:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2408
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# fn bar(b:uint) { }\n"
-"for i in range(0u, 256) {\n"
-"    bar(i);\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2410
-msgid "### If expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2414
-#, no-wrap
-msgid ""
-"~~~~~~~~{.ebnf .gram}\n"
-"if_expr : \"if\" expr '{' block '}'\n"
-"          else_tail ? ;\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2418
-#, no-wrap
-msgid ""
-"else_tail : \"else\" [ if_expr\n"
-"                   | '{' block '}' ] ;\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2429
-msgid ""
-"An `if` expression is a conditional branch in program control. The form of "
-"an `if` expression is a condition expression, followed by a consequent "
-"block, any number of `else if` conditions and blocks, and an optional "
-"trailing `else` block. The condition expressions must have type `bool`. If a "
-"condition expression evaluates to `true`, the consequent block is executed "
-"and any subsequent `else if` or `else` block is skipped. If a condition "
-"expression evaluates to `false`, the consequent block is skipped and any "
-"subsequent `else if` condition is evaluated. If all `if` and `else if` "
-"conditions evaluate to `false` then any `else` block is executed."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2432
-msgid "### Match expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2435
-msgid ""
-"~~~~~~~~{.ebnf .gram} match_expr : \"match\" expr '{' match_arm [ '|' "
-"match_arm ] * '}' ;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2437
-msgid "match_arm : match_pat '=>' [ expr \",\" | '{' block '}' ] ;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2440
-msgid "match_pat : pat [ \"..\" pat ] ? [ \"if\" expr ] ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2448
-msgid ""
-"A `match` expression branches on a *pattern*. The exact form of matching "
-"that occurs depends on the pattern. Patterns consist of some combination of "
-"literals, destructured enum constructors, structures, records and tuples, "
-"variable binding specifications, wildcards (`*`), and placeholders (`_`). A "
-"`match` expression has a *head expression*, which is the value to compare to "
-"the patterns. The type of the patterns must equal the type of the head "
-"expression."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2452
-msgid ""
-"In a pattern whose head expression has an `enum` type, a placeholder (`_`) "
-"stands for a *single* data field, whereas a wildcard `*` stands for *all* "
-"the fields of a particular variant. For example:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2455
-msgid "~~~~ enum List<X> { Nil, Cons(X, @List<X>) }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2457 doc/rust.md:2486
-msgid "let x: List<int> = Cons(10, @Cons(11, @Nil));"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2464
-#, no-wrap
-msgid ""
-"match x {\n"
-"    Cons(_, @Nil) => fail!(\"singleton list\"),\n"
-"    Cons(*)       => return,\n"
-"    Nil           => fail!(\"empty list\")\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2469
-msgid ""
-"The first pattern matches lists constructed by applying `Cons` to any head "
-"value, and a tail value of `@Nil`. The second pattern matches _any_ list "
-"constructed with `Cons`, ignoring the values of its arguments. The "
-"difference between `_` and `*` is that the pattern `C(_)` is only type-"
-"correct if `C` has exactly one argument, while the pattern `C(*)` is type-"
-"correct for any enum variant `C`, regardless of how many arguments `C` has."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2475
-msgid ""
-"To execute an `match` expression, first the head expression is evaluated, "
-"then its value is sequentially compared to the patterns in the arms until a "
-"match is found. The first arm with a matching pattern is chosen as the "
-"branch target of the `match`, any variables bound by the pattern are "
-"assigned to local variables in the arm's block, and control enters the block."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2477
-msgid "An example of an `match` expression:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2482
-msgid "~~~~ # fn process_pair(a: int, b: int) { } # fn process_ten() { }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2484
-msgid "enum List<X> { Nil, Cons(X, @List<X>) }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2502
-#, no-wrap
-msgid ""
-"match x {\n"
-"    Cons(a, @Cons(b, _)) => {\n"
-"        process_pair(a,b);\n"
-"    }\n"
-"    Cons(10, _) => {\n"
-"        process_ten();\n"
-"    }\n"
-"    Nil => {\n"
-"        return;\n"
-"    }\n"
-"    _ => {\n"
-"        fail!();\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2509
-msgid ""
-"Patterns that bind variables default to binding to a copy or move of the "
-"matched value (depending on the matched value's type).  This can be changed "
-"to bind to a borrowed pointer by using the ```ref``` keyword, or to a "
-"mutable borrowed pointer using ```ref mut```."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2520
-msgid ""
-"A pattern that's just an identifier, like `Nil` in the previous answer, "
-"could either refer to an enum variant that's in scope, or bind a new "
-"variable.  The compiler resolves this ambiguity by forbidding variable "
-"bindings that occur in ```match``` patterns from shadowing names of variants "
-"that are in scope.  For example, wherever ```List``` is in scope, a "
-"```match``` pattern would not be able to bind ```Nil``` as a new name.  The "
-"compiler interprets a variable pattern `x` as a binding _only_ if there is "
-"no variant named `x` in scope.  A convention you can use to avoid conflicts "
-"is simply to name variants with upper-case letters, and local variables with "
-"lower-case letters."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2524
-msgid ""
-"Multiple match patterns may be joined with the `|` operator.  A range of "
-"values may be specified with `..`.  For example:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2527
-msgid "~~~~ # let x = 2;"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2534
-#, no-wrap
-msgid ""
-"let message = match x {\n"
-"  0 | 1  => \"not many\",\n"
-"  2 .. 9 => \"a few\",\n"
-"  _      => \"lots\"\n"
-"};\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2538
-msgid ""
-"Range patterns only work on scalar types (like integers and characters; not "
-"like vectors and structs, which have sub-components).  A range pattern may "
-"not be a sub-range of another range pattern inside the same `match`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2543
-msgid ""
-"Finally, match patterns can accept *pattern guards* to further refine the "
-"criteria for matching a case. Pattern guards appear after the pattern and "
-"consist of a bool-typed expression following the `if` keyword. A pattern "
-"guard may refer to the variables bound within the pattern they follow."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2548
-msgid ""
-"~~~~ # let maybe_digit = Some(0); # fn process_digit(i: int) { } # fn "
-"process_other(i: int) { }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2555
-#, no-wrap
-msgid ""
-"let message = match maybe_digit {\n"
-"  Some(x) if x < 10 => process_digit(x),\n"
-"  Some(x) => process_other(x),\n"
-"  None => fail!()\n"
-"};\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2557
-msgid "### Return expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2561
-msgid "~~~~~~~~{.ebnf .gram} return_expr : \"return\" expr ? ; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2566
-msgid ""
-"Return expressions are denoted with the keyword `return`. Evaluating a "
-"`return` expression moves its argument into the output slot of the current "
-"function, destroys the current function activation frame, and transfers "
-"control to the caller frame."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2568
-msgid "An example of a `return` expression:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2577
-#, no-wrap
-msgid ""
-"~~~~\n"
-"fn max(a: int, b: int) -> int {\n"
-"   if a > b {\n"
-"      return a;\n"
-"   }\n"
-"   return b;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2580
-msgid "# Type system"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2582
-msgid "## Types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2585
-msgid ""
-"Every slot, item and value in a Rust program has a type. The _type_ of a "
-"*value* defines the interpretation of the memory holding it."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2589
-msgid ""
-"Built-in types and type-constructors are tightly integrated into the "
-"language, in nontrivial ways that are not possible to emulate in user-"
-"defined types. User-defined types have limited capabilities."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2591
-msgid "### Primitive types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2593
-msgid "The primitive types are the following:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:2599
-msgid ""
-"The \"unit\" type `()`, having the single \"unit\" value `()` (occasionally "
-"called \"nil\").  ^[The \"unit\" value `()` is *not* a sentinel \"null "
-"pointer\" value for reference slots; the \"unit\" type is the implicit "
-"return type from functions otherwise lacking a return type, and can be used "
-"in other contexts (such as message-sending or type-parametric code) as a "
-"zero-size type.]"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:2599
-msgid "The boolean type `bool` with values `true` and `false`."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:2599
-msgid "The machine types."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:2599
-msgid "The machine-dependent integer and floating-point types."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2601
-msgid "#### Machine types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2603
-msgid "The machine types are the following:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:2608
-msgid ""
-"The unsigned word types `u8`, `u16`, `u32` and `u64`, with values drawn from "
-"the integer intervals $[0, 2^8 - 1]$, $[0, 2^{16} - 1]$, $[0, 2^{32} - 1]$ "
-"and $[0, 2^{64} - 1]$ respectively."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:2613
-msgid ""
-"The signed two's complement word types `i8`, `i16`, `i32` and `i64`, with "
-"values drawn from the integer intervals $[-(2^7), 2^7 - 1]$, $[-(2^{15}), "
-"2^{15} - 1]$, $[-(2^{31}), 2^{31} - 1]$, $[-(2^{63}), 2^{63} - 1]$ "
-"respectively."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:2616
-msgid ""
-"The IEEE 754-2008 `binary32` and `binary64` floating-point types: `f32` and "
-"`f64`, respectively."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2618
-msgid "#### Machine-dependent integer types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2623
-msgid ""
-"The Rust type `uint`^[A Rust `uint` is analogous to a C99 `uintptr_t`.] is "
-"an unsigned integer type with target-machine-dependent size. Its size, in "
-"bits, is equal to the number of bits required to hold any memory address on "
-"the target machine."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2628
-msgid ""
-"The Rust type `int`^[A Rust `int` is analogous to a C99 `intptr_t`.] is a "
-"two's complement signed integer type with target-machine-dependent size. Its "
-"size, in bits, is equal to the size of the rust type `uint` on the same "
-"target machine."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2631
-msgid "#### Machine-dependent floating point type"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2638
-msgid ""
-"The Rust type `float` is a machine-specific type equal to one of the "
-"supported Rust floating-point machine types (`f32` or `f64`). It is the "
-"largest floating-point type that is directly supported by hardware on the "
-"target machine, or if the target machine has no floating-point hardware "
-"support, the largest floating-point type supported by the software floating-"
-"point library used to support the other floating-point machine types."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2641
-msgid ""
-"Note that due to the preference for hardware-supported floating-point, the "
-"type `float` may not be equal to the largest *supported* floating-point type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2644
-msgid "### Textual types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2646
-msgid "The types `char` and `str` hold textual data."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2649
-msgid ""
-"A value of type `char` is a Unicode character, represented as a 32-bit "
-"unsigned word holding a UCS-4 codepoint."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2655
-msgid ""
-"A value of type `str` is a Unicode string, represented as a vector of 8-bit "
-"unsigned bytes holding a sequence of UTF-8 codepoints.  Since `str` is of "
-"unknown size, it is not a _first class_ type, but can only be instantiated "
-"through a pointer type, such as `&str`, `@str` or `~str`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2658
-msgid "### Tuple types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2661
-msgid ""
-"The tuple type-constructor forms a new heterogeneous product of values "
-"similar to the record type-constructor. The differences are as follows:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:2664
-msgid "tuple elements cannot be mutable, unlike record fields"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:2664
-msgid ""
-"tuple elements are not named and can be accessed only by pattern-matching"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2668
-msgid ""
-"Tuple types and values are denoted by listing the types or values of their "
-"elements, respectively, in a parenthesized, comma-separated list."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2671
-msgid ""
-"The members of a tuple are laid out in memory contiguously, like a record, "
-"in order specified by the tuple type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2673
-msgid "An example of a tuple type and its use:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2680
-msgid ""
-"~~~~ type Pair<'self> = (int,&'self str); let p: Pair<'static> = (10,\"hello"
-"\"); let (a, b) = p; assert!(b != \"world\"); ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2683
-msgid "### Vector types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2696
-msgid ""
-"The vector type constructor represents a homogeneous array of values of a "
-"given type.  A vector has a fixed size.  (Operations like `vec.push` operate "
-"solely on owned vectors.)  A vector type can be annotated with a _definite_ "
-"size, written with a trailing asterisk and integer literal, such as `[int * "
-"10]`.  Such a definite-sized vector type is a first-class type, since its "
-"size is known statically.  A vector without such a size is said to be of "
-"_indefinite_ size, and is therefore not a _first-class_ type.  An indefinite-"
-"size vector can only be instantiated through a pointer type, such as `&[T]`, "
-"`@[T]` or `~[T]`.  The kind of a vector type depends on the kind of its "
-"element type, as with other simple structural types."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2700
-msgid ""
-"Expressions producing vectors of definite size cannot be evaluated in a "
-"context expecting a vector of indefinite size; one must copy the definite-"
-"sized vector contents into a distinct vector of indefinite size."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2702
-msgid "An example of a vector type and its use:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2708
-msgid ""
-"~~~~ let v: &[int] = &[7, 5, 3]; let i: int = v[2]; assert!(i == 3); ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2711
-msgid ""
-"All in-bounds elements of a vector are always initialized, and access to a "
-"vector is always bounds-checked."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2714
-msgid "### Structure types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2719
-msgid ""
-"A `struct` *type* is a heterogeneous product of other types, called the "
-"*fields* of the type.  ^[`struct` types are analogous `struct` types in C, "
-"the *record* types of the ML family, or the *structure* types of the Lisp "
-"family.]"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2721
-msgid ""
-"New instances of a `struct` can be constructed with a [struct expression]"
-"(#struct-expressions)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2725
-msgid ""
-"The memory order of fields in a `struct` is given by the item defining it.  "
-"Fields may be given in any order in a corresponding struct *expression*; the "
-"resulting `struct` value will always be laid out in memory in the order "
-"specified by the corresponding *item*."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2728
-msgid ""
-"The fields of a `struct` may be qualified by [visibility modifiers]"
-"(#visibility-modifiers), to restrict access to implementation-private data "
-"in a structure."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2730
-msgid ""
-"A _tuple struct_ type is just like a structure type, except that the fields "
-"are anonymous."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2733
-msgid ""
-"A _unit-like struct_ type is like a structure type, except that it has no "
-"fields.  The one value constructed by the associated [structure expression]"
-"(#structure-expression) is the only value that inhabits such a type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2735
-msgid "### Enumerated types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2740
-msgid ""
-"An *enumerated type* is a nominal, heterogeneous disjoint union type, "
-"denoted by the name of an [`enum` item](#enumerations).  ^[The `enum` type "
-"is analogous to a `data` constructor declaration in ML, or a *pick ADT* in "
-"Limbo.]"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2743
-msgid ""
-"An [`enum` item](#enumerations) declares both the type and a number of "
-"*variant constructors*, each of which is independently named and takes an "
-"optional tuple of arguments."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2746
-msgid ""
-"New instances of an `enum` can be constructed by calling one of the variant "
-"constructors, in a [call expression](#call-expressions)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2748
-msgid ""
-"Any `enum` value consumes as much memory as the largest variant constructor "
-"for its corresponding `enum` type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2751
-msgid ""
-"Enum types cannot be denoted *structurally* as types, but must be denoted by "
-"named reference to an [`enum` item](#enumerations)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2754
-msgid "### Recursive types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2758
-msgid ""
-"Nominal types -- [enumerations](#enumerated-types) and [structures]"
-"(#structure-types) -- may be recursive.  That is, each `enum` constructor or "
-"`struct` field may refer, directly or indirectly, to the enclosing `enum` or "
-"`struct` type itself.  Such recursion has restrictions:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2768
-#, no-wrap
-msgid ""
-"* Recursive types must include a nominal type in the recursion\n"
-"  (not mere [type definitions](#type-definitions),\n"
-"   or other structural types such as [vectors](#vector-types) or [tuples](#tuple-types)).\n"
-"* A recursive `enum` item must have at least one non-recursive constructor\n"
-"  (in order to give the recursion a basis case).\n"
-"* The size of a recursive type must be finite;\n"
-"  in other words the recursive fields of the type must be [pointer types](#pointer-types).\n"
-"* Recursive type definitions can cross module boundaries, but not module *visibility* boundaries,\n"
-"  or crate boundaries (in order to simplify the module system and type checker).\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2770
-msgid "An example of a *recursive* type and its use:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2776
-#, no-wrap
-msgid ""
-"~~~~\n"
-"enum List<T> {\n"
-"  Nil,\n"
-"  Cons(T, @List<T>)\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2779
-msgid "let a: List<int> = Cons(7, @Cons(13, @Nil)); ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2782
-msgid "### Pointer types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2786
-msgid ""
-"All pointers in Rust are explicit first-class values.  They can be copied, "
-"stored into data structures, and returned from functions.  There are four "
-"varieties of pointer in Rust:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2796
-#, no-wrap
-msgid ""
-"Managed pointers (`@`)\n"
-"  : These point to managed heap allocations (or \"boxes\") in the task-local, managed heap.\n"
-"    Managed pointers are written `@content`,\n"
-"    for example `@int` means a managed pointer to a managed box containing an integer.\n"
-"    Copying a managed pointer is a \"shallow\" operation:\n"
-"    it involves only copying the pointer itself\n"
-"    (as well as any reference-count or GC-barriers required by the managed heap).\n"
-"    Dropping a managed pointer does not necessarily release the box it points to;\n"
-"    the lifecycles of managed boxes are subject to an unspecified garbage collection algorithm.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2805
-#, no-wrap
-msgid ""
-"Owning pointers (`~`)\n"
-"  : These point to owned heap allocations (or \"boxes\") in the shared, inter-task heap.\n"
-"    Each owned box has a single owning pointer; pointer and pointee retain a 1:1 relationship at all times.\n"
-"    Owning pointers are written `~content`,\n"
-"    for example `~int` means an owning pointer to an owned box containing an integer.\n"
-"    Copying an owned box is a \"deep\" operation:\n"
-"    it involves allocating a new owned box and copying the contents of the old box into the new box.\n"
-"    Releasing an owning pointer immediately releases its corresponding owned box.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2818
-#, no-wrap
-msgid ""
-"Borrowed pointers (`&`)\n"
-"  : These point to memory _owned by some other value_.\n"
-"    Borrowed pointers arise by (automatic) conversion from owning pointers, managed pointers,\n"
-"    or by applying the borrowing operator `&` to some other value,\n"
-"    including [lvalues, rvalues or temporaries](#lvalues-rvalues-and-temporaries).\n"
-"    Borrowed pointers are written `&content`, or in some cases `&f/content` for some lifetime-variable `f`,\n"
-"    for example `&int` means a borrowed pointer to an integer.\n"
-"    Copying a borrowed pointer is a \"shallow\" operation:\n"
-"    it involves only copying the pointer itself.\n"
-"    Releasing a borrowed pointer typically has no effect on the value it points to,\n"
-"    with the exception of temporary values,\n"
-"    which are released when the last borrowed pointer to them is released.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2828
-#, no-wrap
-msgid ""
-"Raw pointers (`*`)\n"
-"  : Raw pointers are pointers without safety or liveness guarantees.\n"
-"    Raw pointers are written `*content`,\n"
-"    for example `*int` means a raw pointer to an integer.\n"
-"    Copying or dropping a raw pointer is has no effect on the lifecycle of any other value.\n"
-"    Dereferencing a raw pointer or converting it to any other pointer type is an [`unsafe` operation](#unsafe-functions).\n"
-"    Raw pointers are generally discouraged in Rust code;\n"
-"    they exist to support interoperability with foreign code,\n"
-"    and writing performance-critical or low-level functions.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2831
-msgid "### Function types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2835
-msgid ""
-"The function type constructor `fn` forms new function types.  A function "
-"type consists of a possibly-empty set of function-type modifiers (such as "
-"`unsafe` or `extern`), a sequence of input types and an output type."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2837
-msgid "An example of a `fn` type:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2842
-#, no-wrap
-msgid ""
-"~~~~~~~~\n"
-"fn add(x: int, y: int) -> int {\n"
-"  return x + y;\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2844
-msgid "let mut x = add(5,7);"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2849
-msgid ""
-"type Binop<'self> = 'self |int,int| -> int; let bo: Binop = add; x = "
-"bo(5,7); ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2851
-msgid "### Object types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2858
-msgid ""
-"Every trait item (see [traits](#traits)) defines a type with the same name "
-"as the trait.  This type is called the _object type_ of the trait.  Object "
-"types permit \"late binding\" of methods, dispatched using _virtual method "
-"tables_ (\"vtables\").  Whereas most calls to trait methods are \"early bound"
-"\" (statically resolved) to specific implementations at compile time, a call "
-"to a method on an object type is only resolved to a vtable entry at compile "
-"time.  The actual implementation for each vtable entry can vary on an object-"
-"by-object basis."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2863
-msgid ""
-"Given a pointer-typed expression `E` of type `&T`, `~T` or `@T`, where `T` "
-"implements trait `R`, casting `E` to the corresponding pointer type `&R`, "
-"`~R` or `@R` results in a value of the _object type_ `R`.  This result is "
-"represented as a pair of pointers: the vtable pointer for the `T` "
-"implementation of `R`, and the pointer value of `E`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2865
-msgid "An example of an object type:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2871
-#, no-wrap
-msgid ""
-"~~~~~~~~\n"
-"# use std::int;\n"
-"trait Printable {\n"
-"  fn to_str(&self) -> ~str;\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2875
-#, no-wrap
-msgid ""
-"impl Printable for int {\n"
-"  fn to_str(&self) -> ~str { int::to_str(*self) }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2879
-#, no-wrap
-msgid ""
-"fn print(a: @Printable) {\n"
-"   println(a.to_str());\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2884
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"   print(@10 as @Printable);\n"
-"}\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2887
-msgid ""
-"In this example, the trait `Printable` occurs as an object type in both the "
-"type signature of `print`, and the cast expression in `main`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2889
-msgid "### Type parameters"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2891
-msgid ""
-"Within the body of an item that has type parameter declarations, the names "
-"of its type parameters are types:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2902
-#, no-wrap
-msgid ""
-"~~~~~~~\n"
-"fn map<A: Clone, B: Clone>(f: |A| -> B, xs: &[A]) -> ~[B] {\n"
-"    if xs.len() == 0 {\n"
-"       return ~[];\n"
-"    }\n"
-"    let first: B = f(xs[0].clone());\n"
-"    let rest: ~[B] = map(f, xs.slice(1, xs.len()));\n"
-"    return ~[first] + rest;\n"
-"}\n"
-"~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2905
-msgid ""
-"Here, `first` has type `B`, referring to `map`'s `B` type parameter; and "
-"`rest` has type `~[B]`, a vector type with element type `B`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2907
-msgid "### Self types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2911
-msgid ""
-"The special type `self` has a meaning within methods inside an impl item. It "
-"refers to the type of the implicit `self` argument. For example, in:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2916
-#, no-wrap
-msgid ""
-"~~~~~~~~\n"
-"trait Printable {\n"
-"  fn make_string(&self) -> ~str;\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2923
-#, no-wrap
-msgid ""
-"impl Printable for ~str {\n"
-"    fn make_string(&self) -> ~str {\n"
-"        (*self).clone()\n"
-"    }\n"
-"}\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2926
-msgid ""
-"`self` refers to the value of type `~str` that is the receiver for a call to "
-"the method `make_string`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2928
-msgid "## Type kinds"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2931
-msgid ""
-"Types in Rust are categorized into kinds, based on various properties of the "
-"components of the type.  The kinds are:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2957
-#, no-wrap
-msgid ""
-"`Freeze`\n"
-"  : Types of this kind are deeply immutable;\n"
-"    they contain no mutable memory locations\n"
-"    directly or indirectly via pointers.\n"
-"`Send`\n"
-"  : Types of this kind can be safely sent between tasks.\n"
-"    This kind includes scalars, owning pointers, owned closures, and\n"
-"    structural types containing only other owned types.\n"
-"    All `Send` types are `'static`.\n"
-"`'static`\n"
-"  : Types of this kind do not contain any borrowed pointers;\n"
-"    this can be a useful guarantee for code\n"
-"    that breaks borrowing assumptions\n"
-"    using [`unsafe` operations](#unsafe-functions).\n"
-"`Drop`\n"
-"  : This is not strictly a kind,\n"
-"    but its presence interacts with kinds:\n"
-"    the `Drop` trait provides a single method `drop`\n"
-"    that takes no parameters,\n"
-"    and is run when values of the type are dropped.\n"
-"    Such a method is called a \"destructor\",\n"
-"    and are always executed in \"top-down\" order:\n"
-"    a value is completely destroyed\n"
-"    before any of the values it owns run their destructors.\n"
-"    Only `Send` types can implement `Drop`.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2964
-#, no-wrap
-msgid ""
-"_Default_\n"
-"  : Types with destructors, closure environments,\n"
-"    and various other _non-first-class_ types,\n"
-"    are not copyable at all.\n"
-"    Such types can usually only be accessed through pointers,\n"
-"    or in some cases, moved between mutable locations.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2967
-msgid ""
-"Kinds can be supplied as _bounds_ on type parameters, like traits, in which "
-"case the parameter is constrained to types satisfying that kind."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2973
-msgid ""
-"By default, type parameters do not carry any assumed kind-bounds at all.  "
-"When instantiating a type parameter, the kind bounds on the parameter are "
-"checked to be the same or narrower than the kind of the type that it is "
-"instantiated with."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2978
-msgid ""
-"Sending operations are not part of the Rust language, but are implemented in "
-"the library.  Generic functions that send values bound the kind of these "
-"values to sendable."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2980
-msgid "# Memory and concurrency models"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2985
-msgid ""
-"Rust has a memory model centered around concurrently-executing _tasks_. Thus "
-"its memory model and its concurrency model are best discussed "
-"simultaneously, as parts of each only make sense when considered from the "
-"perspective of the other."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2990
-msgid ""
-"When reading about the memory model, keep in mind that it is partitioned in "
-"order to support tasks; and when reading about tasks, keep in mind that "
-"their isolation and communication mechanisms are only possible due to the "
-"ownership and lifetime semantics of the memory model."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2992
-msgid "## Memory model"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2996
-msgid ""
-"A Rust program's memory consists of a static set of *items*, a set of [tasks]"
-"(#tasks) each with its own *stack*, and a *heap*. Immutable portions of the "
-"heap may be shared between tasks, mutable portions may not."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:2999
-msgid ""
-"Allocations in the stack consist of *slots*, and allocations in the heap "
-"consist of *boxes*."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3002
-msgid "### Memory allocation and lifetime"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3007
-msgid ""
-"The _items_ of a program are those functions, modules and types that have "
-"their value calculated at compile-time and stored uniquely in the memory "
-"image of the rust process. Items are neither dynamically allocated nor freed."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3011
-msgid ""
-"A task's _stack_ consists of activation frames automatically allocated on "
-"entry to each function as the task executes. A stack allocation is reclaimed "
-"when control leaves the frame containing it."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3018
-msgid ""
-"The _heap_ is a general term that describes two separate sets of boxes: "
-"managed boxes -- which may be subject to garbage collection -- and owned "
-"boxes.  The lifetime of an allocation in the heap depends on the lifetime of "
-"the box values pointing to it. Since box values may themselves be passed in "
-"and out of frames, or stored in the heap, heap allocations may outlive the "
-"frame they are allocated within."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3020
-msgid "### Memory ownership"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3023
-msgid ""
-"A task owns all memory it can *safely* reach through local variables, as "
-"well as managed, owning and borrowed pointers."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3030
-msgid ""
-"When a task sends a value that has the `Send` trait to another task, it "
-"loses ownership of the value sent and can no longer refer to it.  This is "
-"statically guaranteed by the combined use of \"move semantics\", and the "
-"compiler-checked _meaning_ of the `Send` trait: it is only instantiated for "
-"(transitively) sendable kinds of data constructor and pointers, never "
-"including managed or borrowed pointers."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3033
-msgid ""
-"When a stack frame is exited, its local allocations are all released, and "
-"its references to boxes (both managed and owned) are dropped."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3039
-msgid ""
-"A managed box may (in the case of a recursive, mutable managed type) be "
-"cyclic; in this case the release of memory inside the managed structure may "
-"be deferred until task-local garbage collection can reclaim it. Code can "
-"ensure no such delayed deallocation occurs by restricting itself to owned "
-"boxes and similar unmanaged kinds of data."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3042
-msgid ""
-"When a task finishes, its stack is necessarily empty and it therefore has no "
-"references to any boxes; the remainder of its heap is immediately freed."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3045
-msgid "### Memory slots"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3047
-msgid "A task's stack contains slots."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3050
-msgid ""
-"A _slot_ is a component of a stack frame, either a function parameter, a "
-"[temporary](#lvalues-rvalues-and-temporaries), or a local variable."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3053
-msgid ""
-"A _local variable_ (or *stack-local* allocation) holds a value directly, "
-"allocated within the stack's memory. The value is a part of the stack frame."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3058
-msgid ""
-"Local variables are immutable unless declared with `let mut`.  The `mut` "
-"keyword applies to all local variables declared within that declaration (so "
-"`let mut (x, y) = ...` declares two mutable variables, `x` and `y`)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3063
-msgid ""
-"Function parameters are immutable unless declared with `mut`. The `mut` "
-"keyword applies only to the following parameter (so `|mut x, y|` and `fn "
-"f(mut x: ~int, y: ~int)` declare one mutable variable `x` and one immutable "
-"variable `y`)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3069
-msgid ""
-"Local variables are not initialized when allocated; the entire frame worth "
-"of local variables are allocated at once, on frame-entry, in an "
-"uninitialized state. Subsequent statements within a function may or may not "
-"initialize the local variables. Local variables can be used only after they "
-"have been initialized; this is enforced by the compiler."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3072
-msgid "### Memory boxes"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3075
-msgid ""
-"A _box_ is a reference to a heap allocation holding another value. There are "
-"two kinds of boxes: *managed boxes* and *owned boxes*."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3077
-msgid ""
-"A _managed box_ type or value is constructed by the prefix *at* sigil `@`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3079
-msgid ""
-"An _owned box_ type or value is constructed by the prefix *tilde* sigil `~`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3084
-msgid ""
-"Multiple managed box values can point to the same heap allocation; copying a "
-"managed box value makes a shallow copy of the pointer (optionally "
-"incrementing a reference count, if the managed box is implemented through "
-"reference-counting)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3086
-msgid ""
-"Owned box values exist in 1:1 correspondence with their heap allocation."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3089
-msgid ""
-"An example of constructing one managed box type and value, and one owned box "
-"type and value:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3094
-msgid "~~~~~~~~ let x: @int = @10; let x: ~int = ~10; ~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3097
-msgid ""
-"Some operations (such as field selection) implicitly dereference boxes. An "
-"example of an _implicit dereference_ operation performed on box values:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3103
-msgid ""
-"~~~~~~~~ struct Foo { y: int } let x = @Foo{y: 10}; assert!(x.y == 10); "
-"~~~~~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3109
-msgid ""
-"Other operations act on box values as single-word-sized address values. For "
-"these operations, to access the value held in the box requires an explicit "
-"dereference of the box value. Explicitly dereferencing a box is indicated "
-"with the unary *star* operator `*`. Examples of such _explicit dereference_ "
-"operations are:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3112
-msgid "copying box values (`x = y`)"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3112
-msgid "passing box values to functions (`f(x,y)`)"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3115
-msgid ""
-"An example of an explicit-dereference operation performed on box values:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3119
-msgid "~~~~~~~~ fn takes_boxed(b: @int) { }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3122
-msgid "fn takes_unboxed(b: int) { }"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3129
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"    let x: @int = @10;\n"
-"    takes_boxed(x);\n"
-"    takes_unboxed(*x);\n"
-"}\n"
-"~~~~~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3131
-msgid "## Tasks"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3139
-msgid ""
-"An executing Rust program consists of a tree of tasks.  A Rust _task_ "
-"consists of an entry function, a stack, a set of outgoing communication "
-"channels and incoming communication ports, and ownership of some portion of "
-"the heap of a single operating-system process.  (We expect that many "
-"programs will not use channels and ports directly, but will instead use "
-"higher-level abstractions provided in standard libraries, such as pipes.)"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3154
-msgid ""
-"Multiple Rust tasks may coexist in a single operating-system process.  The "
-"runtime scheduler maps tasks to a certain number of operating-system "
-"threads.  By default, the scheduler chooses the number of threads based on "
-"the number of concurrent physical CPUs detected at startup.  It's also "
-"possible to override this choice at runtime.  When the number of tasks "
-"exceeds the number of threads -- which is likely -- the scheduler "
-"multiplexes the tasks onto threads.^[ This is an M:N scheduler, which is "
-"known to give suboptimal results for CPU-bound concurrency problems.  In "
-"such cases, running with the same number of threads and tasks can yield "
-"better results.  Rust has M:N scheduling in order to support very large "
-"numbers of tasks in contexts where threads are too resource-intensive to use "
-"in large number.  The cost of threads varies substantially per operating "
-"system, and is sometimes quite low, so this flexibility is not always worth "
-"exploiting.]"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3157
-msgid "### Communication between tasks"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3162
-msgid ""
-"Rust tasks are isolated and generally unable to interfere with one another's "
-"memory directly, except through [`unsafe` code](#unsafe-functions).  All "
-"contact between tasks is mediated by safe forms of ownership transfer, and "
-"data races on memory are prohibited by the type system."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3165
-msgid ""
-"Inter-task communication and co-ordination facilities are provided in the "
-"standard library.  These include:"
-msgstr ""
-
-#. type: Bullet: '  - '
-#: doc/rust.md:3169
-msgid ""
-"synchronous and asynchronous communication channels with various "
-"communication topologies"
-msgstr ""
-
-#. type: Bullet: '  - '
-#: doc/rust.md:3169
-msgid ""
-"read-only and read-write shared variables with various safe mutual exclusion "
-"patterns"
-msgstr ""
-
-#. type: Bullet: '  - '
-#: doc/rust.md:3169
-msgid "simple locks and semaphores"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3174
-msgid ""
-"When such facilities carry values, the values are restricted to the [`Send` "
-"type-kind](#type-kinds).  Restricting communication interfaces to this kind "
-"ensures that no borrowed or managed pointers move between tasks.  Thus "
-"access to an entire data structure can be mediated through its owning \"root"
-"\" value; no further locking or copying is required to avoid data races "
-"within the substructure of such a value."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3177
-msgid "### Task lifecycle"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3180
-msgid ""
-"The _lifecycle_ of a task consists of a finite set of states and events that "
-"cause transitions between the states. The lifecycle states of a task are:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3185
-msgid "running"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3185
-msgid "blocked"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3185
-msgid "failing"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3185
-msgid "dead"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3189
-msgid ""
-"A task begins its lifecycle -- once it has been spawned -- in the *running* "
-"state. In this state it executes the statements of its entry function, and "
-"any functions called by the entry function."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3195
-msgid ""
-"A task may transition from the *running* state to the *blocked* state any "
-"time it makes a blocking communication call. When the call can be completed "
-"-- when a message arrives at a sender, or a buffer opens to receive a "
-"message -- then the blocked task will unblock and transition back to "
-"*running*."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3214
-msgid ""
-"A task may transition to the *failing* state at any time, due being killed "
-"by some external event or internally, from the evaluation of a `fail!()` "
-"macro. Once *failing*, a task unwinds its stack and transitions to the "
-"*dead* state. Unwinding the stack of a task is done by the task itself, on "
-"its own control stack. If a value with a destructor is freed during "
-"unwinding, the code for the destructor is run, also on the task's control "
-"stack. Running the destructor code causes a temporary transition to a "
-"*running* state, and allows the destructor code to cause any subsequent "
-"state transitions.  The original task of unwinding and failing thereby may "
-"suspend temporarily, and may involve (recursive) unwinding of the stack of a "
-"failed destructor. Nonetheless, the outermost unwinding activity will "
-"continue until the stack is unwound and the task transitions to the *dead* "
-"state. There is no way to \"recover\" from task failure.  Once a task has "
-"temporarily suspended its unwinding in the *failing* state, failure "
-"occurring from within this destructor results in *hard* failure.  The "
-"unwinding procedure of hard failure frees resources but does not execute "
-"destructors.  The original (soft) failure is still resumed at the point "
-"where it was temporarily suspended."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3218
-msgid ""
-"A task in the *dead* state cannot transition to other states; it exists only "
-"to have its termination status inspected by other tasks, and/or to await "
-"reclamation when the last reference to it drops."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3221
-msgid "### Task scheduling"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3225
-msgid ""
-"The currently scheduled task is given a finite *time slice* in which to "
-"execute, after which it is *descheduled* at a loop-edge or similar "
-"preemption point, and another task within is scheduled, pseudo-randomly."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3229
-msgid ""
-"An executing task can yield control at any time, by making a library call to "
-"`std::task::yield`, which deschedules it immediately. Entering any other non-"
-"executing state (blocked, dead) similarly deschedules the task."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3232
-msgid "# Runtime services, linkage and debugging"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3239
-msgid ""
-"The Rust _runtime_ is a relatively compact collection of C++ and Rust code "
-"that provides fundamental services and datatypes to all Rust tasks at run-"
-"time. It is smaller and simpler than many modern language runtimes. It is "
-"tightly integrated into the language's execution model of memory, tasks, "
-"communication and logging."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3241
-msgid ""
-"> **Note:** The runtime library will merge with the `std` library in future "
-"versions of Rust."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3243
-msgid "### Memory allocation"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3249
-msgid ""
-"The runtime memory-management system is based on a _service-provider "
-"interface_, through which the runtime requests blocks of memory from its "
-"environment and releases them back to its environment when they are no "
-"longer needed.  The default implementation of the service-provider interface "
-"consists of the C runtime functions `malloc` and `free`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3253
-msgid ""
-"The runtime memory-management system, in turn, supplies Rust tasks with "
-"facilities for allocating, extending and releasing stacks, as well as "
-"allocating and freeing heap data."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3255
-msgid "### Built in types"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3259
-msgid ""
-"The runtime provides C and Rust code to assist with various built-in types, "
-"such as vectors, strings, and the low level communication system (ports, "
-"channels, tasks)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3262
-msgid ""
-"Support for other built-in types such as simple types, tuples, records, and "
-"enums is open-coded by the Rust compiler."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3266
-msgid "### Task scheduling and communication"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3272
-msgid ""
-"The runtime provides code to manage inter-task communication.  This includes "
-"the system of task-lifecycle state transitions depending on the contents of "
-"queues, as well as code to copy values between queues and their recipients "
-"and to serialize values for transmission over operating-system inter-process "
-"communication facilities."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3275
-msgid "### Logging system"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3279
-msgid ""
-"The runtime contains a system for directing [logging expressions](#log-"
-"expressions) to a logging console and/or internal logging buffers. Logging "
-"can be enabled per module."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3286
-msgid ""
-"Logging output is enabled by setting the `RUST_LOG` environment variable.  "
-"`RUST_LOG` accepts a logging specification made up of a comma-separated list "
-"of paths, with optional log levels. For each module containing log "
-"expressions, if `RUST_LOG` contains the path to that module or a parent of "
-"that module, then logs of the appropriate level will be output to the "
-"console."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3294
-msgid ""
-"The path to a module consists of the crate name, any parent modules, then "
-"the module itself, all separated by double colons (`::`).  The optional log "
-"level can be appended to the module path with an equals sign (`=`) followed "
-"by the log level, from 1 to 4, inclusive. Level 1 is the error level, 2 is "
-"warning, 3 info, and 4 debug. Any logs less than or equal to the specified "
-"level will be output. If not specified then log level 4 is assumed."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3300
-msgid ""
-"As an example, to see all the logs generated by the compiler, you would set "
-"`RUST_LOG` to `rustc`, which is the crate name (as specified in its `link` "
-"[attribute](#attributes)). To narrow down the logs to just crate resolution, "
-"you would set it to `rustc::metadata::creader`. To see just error logging "
-"use `rustc=0`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3305
-msgid ""
-"Note that when compiling source files that don't specify a crate name the "
-"crate is given a default name that matches the source file, with the "
-"extension removed. In that case, to turn on logging for a program compiled "
-"from, e.g. `helloworld.rs`, `RUST_LOG` should be set to `helloworld`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3309
-msgid ""
-"As a convenience, the logging spec can also be set to a special pseudo-"
-"crate, `::help`. In this case, when the application starts, the runtime will "
-"simply output a list of loaded modules containing log expressions, then exit."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3314
-msgid ""
-"The Rust runtime itself generates logging information. The runtime's logs "
-"are generated for a number of artificial modules in the `::rt` pseudo-crate, "
-"and can be enabled just like the logs for any standard module. The full list "
-"of runtime logging modules follows."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::mem` Memory management"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::comm` Messaging and task communication"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::task` Task management"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::dom` Task scheduling"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::trace` Unused"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::cache` Type descriptor cache"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::upcall` Compiler-generated runtime calls"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::timer` The scheduler timer"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::gc` Garbage collection"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::stdlib` Functions used directly by the standard library"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::kern` The runtime kernel"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::backtrace` Log a backtrace on task failure"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3328
-msgid "`::rt::callback` Unused"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3330
-msgid "#### Logging Expressions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3333
-msgid ""
-"Rust provides several macros to log information. Here's a simple Rust "
-"program that demonstrates all four of them:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3342
-#, no-wrap
-msgid ""
-"```rust\n"
-"fn main() {\n"
-"    error!(\"This is an error log\")\n"
-"    warn!(\"This is a warn log\")\n"
-"    info!(\"this is an info log\")\n"
-"    debug!(\"This is a debug log\")\n"
-"}\n"
-"```\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3344
-msgid ""
-"These four log levels correspond to levels 1-4, as controlled by `RUST_LOG`:"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3351
-msgid ""
-"```bash $ RUST_LOG=rust=3 ./rust rust: ~\"\\\"This is an error log\\\"\" "
-"rust: ~\"\\\"This is a warn log\\\"\" rust: ~\"\\\"this is an info log\\\"\" "
-"```"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3353
-msgid "# Appendix: Rationales and design tradeoffs"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3355
-#, no-wrap
-msgid "*TODO*.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3357
-msgid "# Appendix: Influences and further references"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3359
+#: doc/rust.md:3861
+#, fuzzy
 msgid "## Influences"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3368
-msgid ""
-"> The essential problem that must be solved in making a fault-tolerant > "
-"software system is therefore that of fault-isolation. Different programmers "
-"> will write different modules, some modules will be correct, others will "
-"have > errors. We do not want the errors in one module to adversely affect "
-"the > behaviour of a module which does not have any errors.  > > &mdash; Joe "
-"Armstrong"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3380
-msgid ""
-"> In our approach, all data is private to some process, and processes can > "
-"only communicate through communications channels. *Security*, as used > in "
-"this paper, is the property which guarantees that processes in a system > "
-"cannot affect each other except by explicit communication.  > > When "
-"security is absent, nothing which can be proven about a single module > in "
-"isolation can be guaranteed to hold when that module is embedded in a > "
-"system [...] > > &mdash; Robert Strom and Shaula Yemini"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3388
-msgid ""
-"> Concurrent and applicative programming complement each other. The > "
-"ability to send messages on channels provides I/O without side effects, > "
-"while the avoidance of shared data helps keep concurrent processes from > "
-"colliding.  > > &mdash; Rob Pike"
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3395
-msgid ""
-"Rust is not a particularly original language. It may however appear unusual "
-"by contemporary standards, as its design elements are drawn from a number of "
-"\"historical\" languages that have, with a few exceptions, fallen out of "
-"favour. Five prominent lineages contribute the most, though their influences "
-"have come and gone during the course of Rust's development:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3399
-msgid ""
-"The NIL (1981) and Hermes (1990) family. These languages were developed by "
-"Robert Strom, Shaula Yemini, David Bacon and others in their group at IBM "
-"Watson Research Center (Yorktown Heights, NY, USA)."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3403
-msgid ""
-"The Erlang (1987) language, developed by Joe Armstrong, Robert Virding, "
-"Claes Wikstr&ouml;m, Mike Williams and others in their group at the Ericsson "
-"Computer Science Laboratory (&Auml;lvsj&ouml;, Stockholm, Sweden) ."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3408
-msgid ""
-"The Sather (1990) language, developed by Stephen Omohundro, Chu-Cheow Lim, "
-"Heinz Schmidt and others in their group at The International Computer "
-"Science Institute of the University of California, Berkeley (Berkeley, CA, "
-"USA)."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3413
-msgid ""
-"The Newsqueak (1988), Alef (1995), and Limbo (1996) family. These languages "
-"were developed by Rob Pike, Phil Winterbottom, Sean Dorward and others in "
-"their group at Bell Labs Computing Sciences Research Center (Murray Hill, "
-"NJ, USA)."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3417
-msgid ""
-"The Napier (1985) and Napier88 (1988) family. These languages were developed "
-"by Malcolm Atkinson, Ron Morrison and others in their group at the "
-"University of St. Andrews (St. Andrews, Fife, UK)."
-msgstr ""
-
-#. type: Plain text
-#: doc/rust.md:3419
-msgid ""
-"Additional specific influences can be seen from the following languages:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3427
-msgid "The stack-growth implementation of Go."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3427
-msgid "The structural algebraic types and compilation manager of SML."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3427
-msgid "The attribute and assembly systems of C#."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3427
-msgid "The references and deterministic destructor system of C++."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3427
-msgid "The memory region systems of the ML Kit and Cyclone."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3427
-msgid "The typeclass system of Haskell."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3427
-msgid "The lexical identifier rule of Python."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rust.md:3427
-msgid "The block syntax of Ruby."
-msgstr ""
+msgstr "# ポインタのデリファレンス"
diff --git a/doc/po/ja/rustdoc.md.po b/doc/po/ja/rustdoc.md.po
new file mode 100644 (file)
index 0000000..9d5146e
--- /dev/null
@@ -0,0 +1,52 @@
+# Japanese translations for Rust package
+# Copyright (C) 2014 The Rust Project Developers
+# This file is distributed under the same license as the Rust package.
+# Automatically generated, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Rust 0.10-pre\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
+"PO-Revision-Date: 2014-01-13 12:01+0900\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. type: Plain text
+#: doc/rustdoc.md:2
+#, fuzzy
+#| msgid "## Using the rust tool"
+msgid "% Rust Documentation"
+msgstr "## `rust` コマンドを利用する"
+
+#. type: Plain text
+#: doc/rustdoc.md:9
+#, fuzzy
+#| msgid "## Using the rust tool"
+msgid "# Creating Documentation"
+msgstr "## `rust` コマンドを利用する"
+
+#. type: Plain text
+#: doc/rustdoc.md:79
+#, fuzzy
+#| msgid "## Using the rust tool"
+msgid "# Using the Documentation"
+msgstr "## `rust` コマンドを利用する"
+
+#. type: Plain text
+#: doc/rustdoc.md:90
+#, fuzzy
+#| msgid "## Using the rust tool"
+msgid "# Testing the Documentation"
+msgstr "## `rust` コマンドを利用する"
+
+#. type: Plain text
+#: doc/rustdoc.md:102
+#, fuzzy
+#| msgid "# Dereferencing pointers"
+msgid "## Defining tests"
+msgstr "# ポインタのデリファレンス"
index 699e17eb9520fcc0a847cf50cb6557c536b87dcf..4df7d2fa5832fda67b2359e8c5c800700a618488 100644 (file)
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: Rust 0.8\n"
-"POT-Creation-Date: 2013-07-30 07:07+0900\n"
+"POT-Creation-Date: 2014-01-13 12:01+0900\n"
 "PO-Revision-Date: 2013-07-28 20:32+0900\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -17,307 +17,49 @@ msgstr ""
 "Plural-Forms: nplurals=1; plural=0;\n"
 
 #. type: Plain text
+#: doc/guide-conditions.md:4 doc/guide-ffi.md:4 doc/guide-lifetimes.md:4
+#: doc/guide-macros.md:4 doc/guide-rustpkg.md:4 doc/guide-tasks.md:4
 #: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
-#: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
-#: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
 msgid "# Introduction"
 msgstr "# イントロダクション"
 
-#. type: Plain text
-#: doc/rust.md:30 doc/rustpkg.md:8
-msgid "## Disclaimer"
-msgstr ""
-
 #. type: Plain text
 #: doc/rustpkg.md:2
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
 msgid "% Rustpkg Reference Manual"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:6
-msgid ""
-"This document is the reference manual for the Rustpkg packaging and build "
-"tool for the Rust programming language."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:12
-msgid ""
-"Rustpkg is a work in progress, as is this reference manual.  If the actual "
-"behavior of rustpkg differs from the behavior described in this reference, "
-"that reflects either an incompleteness or a bug in rustpkg."
-msgstr ""
+msgstr "% Rust 言語チュートリアル"
 
 #. type: Plain text
 #: doc/rustpkg.md:14
+#, fuzzy
+#| msgid "## Pattern matching"
 msgid "# Package searching"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:17
-msgid ""
-"rustpkg searches for packages using the `RUST_PATH` environment variable, "
-"which is a colon-separated list (semicolon-separated on Windows) of "
-"directories."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:19
-msgid "Each directory in this list is a *workspace* for rustpkg."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:30
-msgid ""
-"`RUST_PATH` implicitly contains an entry for `./.rust` (as well as `../."
-"rust`, `../../.rust`, and so on for every parent of `.` up to the filesystem "
-"root).  That means that if `RUST_PATH` is not set, then rustpkg will still "
-"search for workspaces in `./.rust` and so on.  `RUST_PATH` also implicitly "
-"contains an entry for the system path: `/usr/local` or the equivalent on "
-"Windows.  This entry comes after the implicit entries for `./.rust` and so "
-"on.  Finally, the last implicit entry in `RUST_PATH` is `~/.rust` or the "
-"equivalent on Windows."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:32
-msgid "Each workspace may contain one or more packages."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:38
-msgid ""
-"When building code that contains one or more directives of the form `extern "
-"mod P`, rustpkg automatically searches for packages named `P` in the "
-"`RUST_PATH` (as described above).  It builds those dependencies if "
-"necessary.  Thus, when using rustpkg, there is no need for `-L` flags to "
-"tell the linker where to find libraries for external crates."
-msgstr ""
+msgstr "## パターンマッチ"
 
 #. type: Plain text
 #: doc/rustpkg.md:40
+#, fuzzy
+#| msgid "# Data structures"
 msgid "# Package structure"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:42
-msgid "A valid workspace must contain each of the following subdirectories:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rustpkg.md:44
-msgid ""
-"'src/': contains one subdirectory per package. Each subdirectory contains "
-"source files for a given package."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:49
-#, no-wrap
-msgid ""
-"     For example, if `foo` is a workspace containing the package `bar`,\n"
-"     then `foo/src/bar/main.rs` could be the `main` entry point for\n"
-"     building a `bar` executable.\n"
-"* 'lib/': `rustpkg install` installs libraries into a target-specific subdirectory of this directory.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:56
-#, no-wrap
-msgid ""
-"     For example, on a 64-bit machine running Mac OS X,\n"
-"     if `foo` is a workspace containing the package `bar`,\n"
-"     rustpkg will install libraries for bar to `foo/lib/x86_64-apple-darwin/`.\n"
-"     The libraries will have names of the form `foo/lib/x86_64-apple-darwin/libbar-[hash].dylib`,\n"
-"     where [hash] is a hash of the package ID.\n"
-"* 'bin/': `rustpkg install` installs executable binaries into a target-specific subdirectory of this directory.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:63
-#, no-wrap
-msgid ""
-"     For example, on a 64-bit machine running Mac OS X,\n"
-"     if `foo` is a workspace, containing the package `bar`,\n"
-"     rustpkg will install executables for `bar` to\n"
-"     `foo/bin/x86_64-apple-darwin/`.\n"
-"     The executables will have names of the form `foo/bin/x86_64-apple-darwin/bar`.\n"
-"* 'build/': `rustpkg build` stores temporary build artifacts in a target-specific subdirectory of this directory.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:67
-#, no-wrap
-msgid ""
-"     For example, on a 64-bit machine running Mac OS X,\n"
-"     if `foo` is a workspace containing the package `bar` and `foo/src/bar/main.rs` exists,\n"
-"     then `rustpkg build` will create `foo/build/x86_64-apple-darwin/bar/main.o`.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:69
-msgid "# Package identifiers"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:87
-msgid ""
-"A package identifier identifies a package uniquely.  A package can be stored "
-"in a workspace on the local file system, or on a remote Web server, in which "
-"case the package ID resembles a URL.  For example, `github.com/mozilla/rust` "
-"is a package ID that would refer to the git repository browsable at `http://"
-"github.com/mozilla/rust`.  A package ID can also specify a version, like: "
-"`github.com/mozilla/rust#0.3`.  In this case, `rustpkg` will check that the "
-"repository `github.com/mozilla/rust` has a tag named `0.3`, and report an "
-"error otherwise.  A package ID can also specify a particular revision of a "
-"repository, like: `github.com/mozilla/rust#release-0.7`.  When the refspec "
-"(portion of the package ID after the `#`) can't be parsed as a decimal "
-"number, rustpkg passes the refspec along to the version control system "
-"without interpreting it.  rustpkg also interprets any dependencies on such a "
-"package ID literally (as opposed to versions, where a newer version "
-"satisfies a dependency on an older version).  Thus, `github.com/mozilla/"
-"rust#5c4cd30f80` is also a valid package ID, since git can deduce that "
-"5c4cd30f80 refers to a revision of the desired repository."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:89
-msgid "## Source files"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:91
-msgid ""
-"rustpkg searches for four different fixed filenames in order to determine "
-"the crates to build:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rustpkg.md:96
-msgid "`main.rs`: Assumed to be a main entry point for building an executable."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rustpkg.md:96
-msgid "`lib.rs`: Assumed to be a library crate."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rustpkg.md:96
-msgid ""
-"`test.rs`: Assumed to contain tests declared with the `#[test]` attribute."
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/rustpkg.md:96
-msgid ""
-"`bench.rs`: Assumed to contain benchmarks declared with the `#[bench]` "
-"attribute."
-msgstr ""
+msgstr "# データ構造"
 
 #. type: Plain text
-#: doc/rustpkg.md:98
+#: doc/rustpkg.md:106
+#, fuzzy
+#| msgid "## Conventions"
 msgid "## Versions"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:105
-msgid ""
-"`rustpkg` packages do not need to declare their versions with an attribute "
-"inside one of the source files, because `rustpkg` infers it from the version "
-"control system.  When building a package that is in a `git` repository, "
-"`rustpkg` assumes that the most recent tag specifies the current version.  "
-"When building a package that is not under version control, or that has no "
-"tags, `rustpkg` assumes the intended version is 0.1."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:107
-msgid "# Dependencies"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:111
-msgid ""
-"rustpkg infers dependencies from `extern mod` directives.  Thus, there "
-"should be no need to pass a `-L` flag to rustpkg to tell it where to find a "
-"library.  (In the future, it will also be possible to write an `extern mod` "
-"directive referring to a remote package.)"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:113
-msgid "# Custom build scripts"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:117
-msgid ""
-"A file called `pkg.rs` at the root level in a workspace is called a *package "
-"script*.  If a package script exists, rustpkg executes it to build the "
-"package rather than inferring crates as described previously."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:121
-msgid ""
-"Inside `pkg.rs`, it's possible to call back into rustpkg to finish up the "
-"build.  `rustpkg::api` contains functions to build, install, or clean "
-"libraries and executables in the way rustpkg normally would without custom "
-"build logic."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:123
-msgid "# Command reference"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:125
-msgid "## build"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:131
-msgid ""
-"`rustpkg build foo` searches for a package with ID `foo` and builds it in "
-"any workspace(s) where it finds one.  Supposing such packages are found in "
-"workspaces X, Y, and Z, the command leaves behind files in `X`'s, `Y`'s, and "
-"`Z`'s `build` directories, but not in their `lib` or `bin` directories."
-msgstr ""
+msgstr "## 本書の表記について"
 
 #. type: Plain text
 #: doc/rustpkg.md:133
-msgid "## clean"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:135
-msgid "`rustpkg clean foo` deletes the contents of `foo`'s `build` directory."
-msgstr ""
+#, fuzzy
+msgid "# Command reference"
+msgstr "# ポインタのデリファレンス"
 
 #. type: Plain text
-#: doc/rustpkg.md:137
+#: doc/rustpkg.md:150
+#, fuzzy
+#| msgid "# Introduction"
 msgid "## install"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:141
-msgid ""
-"`rustpkg install foo` builds the libraries and/or executables that are "
-"targets for `foo`, and then installs them either into `foo`'s `lib` and "
-"`bin` directories, or into the `lib` and `bin` subdirectories of the first "
-"entry in `RUST_PATH`."
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:143
-msgid "## test"
-msgstr ""
-
-#. type: Plain text
-#: doc/rustpkg.md:145
-msgid ""
-"`rustpkg test foo` builds `foo`'s `test.rs` file if necessary, then runs the "
-"resulting test executable."
-msgstr ""
+msgstr "# イントロダクション"
diff --git a/doc/po/ja/tutorial-borrowed-ptr.md.po b/doc/po/ja/tutorial-borrowed-ptr.md.po
deleted file mode 100644 (file)
index 19bf3ad..0000000
+++ /dev/null
@@ -1,1071 +0,0 @@
-# Japanese translations for Rust package
-# Copyright (C) 2013 The Rust Project Developers
-# This file is distributed under the same license as the Rust package.
-# Automatically generated, 2013.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Rust 0.8\n"
-"POT-Creation-Date: 2013-07-22 23:37+0900\n"
-"PO-Revision-Date: 2013-07-28 20:32+0900\n"
-"Last-Translator: Automatically generated\n"
-"Language-Team: none\n"
-"Language: ja\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. type: Plain text
-#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
-#: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
-#: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
-msgid "# Introduction"
-msgstr "# イントロダクション"
-
-#. type: Plain text
-#: doc/tutorial.md:1108 doc/tutorial-borrowed-ptr.md:72
-msgid "Now we can call `compute_distance()` in various ways:"
-msgstr ""
-"上記の `compute_distance()` 関数は、様々な方法で呼び出すことができます。"
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:2
-msgid "% Rust Borrowed Pointers Tutorial"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:14
-msgid ""
-"Borrowed pointers are one of the more flexible and powerful tools available "
-"in Rust. A borrowed pointer can point anywhere: into the managed or exchange "
-"heap, into the stack, and even into the interior of another data structure. "
-"A borrowed pointer is as flexible as a C pointer or C++ reference. However, "
-"unlike C and C++ compilers, the Rust compiler includes special static checks "
-"that ensure that programs use borrowed pointers safely. Another advantage of "
-"borrowed pointers is that they are invisible to the garbage collector, so "
-"working with borrowed pointers helps reduce the overhead of automatic memory "
-"management."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:18
-msgid ""
-"Despite their complete safety, a borrowed pointer's representation at "
-"runtime is the same as that of an ordinary pointer in a C program. They "
-"introduce zero overhead. The compiler does all safety checks at compile time."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:24
-msgid ""
-"Although borrowed pointers have rather elaborate theoretical underpinnings "
-"(region pointers), the core concepts will be familiar to anyone who has "
-"worked with C or C++. Therefore, the best way to explain how they are used—"
-"and their limitations—is probably just to work through several examples."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:26
-msgid "# By example"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:31
-msgid ""
-"Borrowed pointers are called *borrowed* because they are only valid for a "
-"limited duration. Borrowed pointers never claim any kind of ownership over "
-"the data that they point to: instead, they are used for cases where you "
-"would like to use data for a short time."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:33
-msgid "As an example, consider a simple struct type `Point`:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:37
-msgid "~~~ struct Point {x: float, y: float} ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:41
-msgid ""
-"We can use this simple definition to allocate points in many different ways. "
-"For example, in this code, each of these three local variables contains a "
-"point, but allocated in a different place:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:48
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point {x: float, y: float}\n"
-"let on_the_stack :  Point =  Point {x: 3.0, y: 4.0};\n"
-"let managed_box  : @Point = @Point {x: 5.0, y: 1.0};\n"
-"let owned_box    : ~Point = ~Point {x: 7.0, y: 9.0};\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:60
-msgid ""
-"Suppose we wanted to write a procedure that computed the distance between "
-"any two points, no matter where they were stored. For example, we might like "
-"to compute the distance between `on_the_stack` and `managed_box`, or between "
-"`managed_box` and `owned_box`. One option is to define a function that takes "
-"two arguments of type `Point`—that is, it takes the points by value. But if "
-"we define it this way, calling the function will cause the points to be "
-"copied. For points, this is probably not so bad, but often copies are "
-"expensive. Worse, if the data type contains mutable fields, copying can "
-"change the semantics of your program in unexpected ways. So we'd like to "
-"define a function that takes the points by pointer. We can use borrowed "
-"pointers to do this:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:70
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point {x: float, y: float}\n"
-"# fn sqrt(f: float) -> float { 0f }\n"
-"fn compute_distance(p1: &Point, p2: &Point) -> float {\n"
-"    let x_d = p1.x - p2.x;\n"
-"    let y_d = p1.y - p2.y;\n"
-"    sqrt(x_d * x_d + y_d * y_d)\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:82
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point {x: float, y: float}\n"
-"# let on_the_stack :  Point =  Point{x: 3.0, y: 4.0};\n"
-"# let managed_box  : @Point = @Point{x: 5.0, y: 1.0};\n"
-"# let owned_box    : ~Point = ~Point{x: 7.0, y: 9.0};\n"
-"# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }\n"
-"compute_distance(&on_the_stack, managed_box);\n"
-"compute_distance(managed_box, owned_box);\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:89
-msgid ""
-"Here, the `&` operator takes the address of the variable `on_the_stack`; "
-"this is because `on_the_stack` has the type `Point` (that is, a struct "
-"value) and we have to take its address to get a value. We also call this "
-"_borrowing_ the local variable `on_the_stack`, because we have created an "
-"alias: that is, another name for the same data."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:95
-msgid ""
-"In contrast, we can pass the boxes `managed_box` and `owned_box` to "
-"`compute_distance` directly. The compiler automatically converts a box like "
-"`@Point` or `~Point` to a borrowed pointer like `&Point`. This is another "
-"form of borrowing: in this case, the caller lends the contents of the "
-"managed or owned box to the callee."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:105
-msgid ""
-"Whenever a caller lends data to a callee, there are some limitations on what "
-"the caller can do with the original. For example, if the contents of a "
-"variable have been lent out, you cannot send that variable to another task. "
-"In addition, the compiler will reject any code that might cause the borrowed "
-"value to be freed or overwrite its component fields with values of different "
-"types (I'll get into what kinds of actions those are shortly). This rule "
-"should make intuitive sense: you must wait for a borrower to return the "
-"value that you lent it (that is, wait for the borrowed pointer to go out of "
-"scope)  before you can make full use of it again."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:107
-msgid "# Other uses for the & operator"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:109
-msgid "In the previous example, the value `on_the_stack` was defined like so:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:114
-msgid ""
-"~~~ # struct Point {x: float, y: float} let on_the_stack: Point = Point {x: "
-"3.0, y: 4.0}; ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:119
-msgid ""
-"This declaration means that code can only pass `Point` by value to other "
-"functions. As a consequence, we had to explicitly take the address of "
-"`on_the_stack` to get a borrowed pointer. Sometimes however it is more "
-"convenient to move the & operator into the definition of `on_the_stack`:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:124
-msgid ""
-"~~~ # struct Point {x: float, y: float} let on_the_stack2: &Point = &Point "
-"{x: 3.0, y: 4.0}; ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:128
-msgid ""
-"Applying `&` to an rvalue (non-assignable location) is just a convenient "
-"shorthand for creating a temporary and taking its address. A more verbose "
-"way to write the same code is:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:134
-msgid ""
-"~~~ # struct Point {x: float, y: float} let tmp = Point {x: 3.0, y: 4.0}; "
-"let on_the_stack2 : &Point = &tmp; ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:136
-msgid "# Taking the address of fields"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:141
-msgid ""
-"As in C, the `&` operator is not limited to taking the address of local "
-"variables. It can also take the address of fields or individual array "
-"elements. For example, consider this type definition for `rectangle`:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:147
-msgid ""
-"~~~ struct Point {x: float, y: float} // as before struct Size {w: float, h: "
-"float} // as before struct Rectangle {origin: Point, size: Size} ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:149
-msgid "Now, as before, we can define rectangles in a few different ways:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:161
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point {x: float, y: float}\n"
-"# struct Size {w: float, h: float} // as before\n"
-"# struct Rectangle {origin: Point, size: Size}\n"
-"let rect_stack   = &Rectangle {origin: Point {x: 1f, y: 2f},\n"
-"                               size: Size {w: 3f, h: 4f}};\n"
-"let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f},\n"
-"                               size: Size {w: 3f, h: 4f}};\n"
-"let rect_owned   = ~Rectangle {origin: Point {x: 5f, y: 6f},\n"
-"                               size: Size {w: 3f, h: 4f}};\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:164
-msgid ""
-"In each case, we can extract out individual subcomponents with the `&` "
-"operator. For example, I could write:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:175
-msgid ""
-"~~~ # struct Point {x: float, y: float} // as before # struct Size {w: "
-"float, h: float} // as before # struct Rectangle {origin: Point, size: Size} "
-"# let rect_stack = &Rectangle {origin: Point {x: 1f, y: 2f}, size: Size {w: "
-"3f, h: 4f}}; # let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f}, "
-"size: Size {w: 3f, h: 4f}}; # let rect_owned = ~Rectangle {origin: Point {x: "
-"5f, y: 6f}, size: Size {w: 3f, h: 4f}}; # fn compute_distance(p1: &Point, "
-"p2: &Point) -> float { 0f } compute_distance(&rect_stack.origin, "
-"&rect_managed.origin); ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:178
-msgid ""
-"which would borrow the field `origin` from the rectangle on the stack as "
-"well as from the managed box, and then compute the distance between them."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:180
-msgid "# Borrowing managed boxes and rooting"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:186
-msgid ""
-"We’ve seen a few examples so far of borrowing heap boxes, both managed and "
-"owned. Up till this point, we’ve glossed over issues of safety. As stated in "
-"the introduction, at runtime a borrowed pointer is simply a pointer, nothing "
-"more. Therefore, avoiding C's problems with dangling pointers requires a "
-"compile-time safety check."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:197
-msgid ""
-"The basis for the check is the notion of _lifetimes_. A lifetime is a static "
-"approximation of the span of execution during which the pointer is valid: it "
-"always corresponds to some expression or block within the program. Code "
-"inside that expression can use the pointer without restrictions. But if the "
-"pointer escapes from that expression (for example, if the expression "
-"contains an assignment expression that assigns the pointer to a mutable "
-"field of a data structure with a broader scope than the pointer itself), the "
-"compiler reports an error. We'll be discussing lifetimes more in the "
-"examples to come, and a more thorough introduction is also available."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:202
-msgid ""
-"When the `&` operator creates a borrowed pointer, the compiler must ensure "
-"that the pointer remains valid for its entire lifetime. Sometimes this is "
-"relatively easy, such as when taking the address of a local variable or a "
-"field that is stored on the stack:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:211
-#, no-wrap
-msgid ""
-"~~~\n"
-"struct X { f: int }\n"
-"fn example1() {\n"
-"    let mut x = X { f: 3 };\n"
-"    let y = &mut x.f;  // -+ L\n"
-"    ...                //  |\n"
-"}                      // -+\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:216
-msgid ""
-"Here, the lifetime of the borrowed pointer `y` is simply L, the remainder of "
-"the function body. The compiler need not do any other work to prove that "
-"code will not free `x.f`. This is true even if the code mutates `x`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:218
-msgid "The situation gets more complex when borrowing data inside heap boxes:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:227
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct X { f: int }\n"
-"fn example2() {\n"
-"    let mut x = @X { f: 3 };\n"
-"    let y = &x.f;      // -+ L\n"
-"    ...                //  |\n"
-"}                      // -+\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:238
-msgid ""
-"In this example, the value `x` is a heap box, and `y` is therefore a pointer "
-"into that heap box. Again the lifetime of `y` is L, the remainder of the "
-"function body. But there is a crucial difference: suppose `x` were to be "
-"reassigned during the lifetime L? If the compiler isn't careful, the managed "
-"box could become *unrooted*, and would therefore be subject to garbage "
-"collection. A heap box that is unrooted is one such that no pointer values "
-"in the heap point to it. It would violate memory safety for the box that was "
-"originally assigned to `x` to be garbage-collected, since a non-heap pointer "
-"*`y`* still points into it."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:241
-msgid ""
-"> ***Note:*** Our current implementation implements the garbage collector > "
-"using reference counting and cycle detection."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:247
-msgid ""
-"For this reason, whenever an `&` expression borrows the interior of a "
-"managed box stored in a mutable location, the compiler inserts a temporary "
-"that ensures that the managed box remains live for the entire lifetime. So, "
-"the above example would be compiled as if it were written"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:257
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct X { f: int }\n"
-"fn example2() {\n"
-"    let mut x = @X {f: 3};\n"
-"    let x1 = x;\n"
-"    let y = &x1.f;     // -+ L\n"
-"    ...                //  |\n"
-"}                      // -+\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:260
-msgid ""
-"Now if `x` is reassigned, the pointer `y` will still remain valid. This "
-"process is called *rooting*."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:262
-msgid "# Borrowing owned boxes"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:268
-msgid ""
-"The previous example demonstrated *rooting*, the process by which the "
-"compiler ensures that managed boxes remain live for the duration of a "
-"borrow. Unfortunately, rooting does not work for borrows of owned boxes, "
-"because it is not possible to have two references to a owned box."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:274
-msgid ""
-"For owned boxes, therefore, the compiler will only allow a borrow *if the "
-"compiler can guarantee that the owned box will not be reassigned or moved "
-"for the lifetime of the pointer*. This does not necessarily mean that the "
-"owned box is stored in immutable memory. For example, the following function "
-"is legal:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:289
-#, no-wrap
-msgid ""
-"~~~\n"
-"# fn some_condition() -> bool { true }\n"
-"# struct Foo { f: int }\n"
-"fn example3() -> int {\n"
-"    let mut x = ~Foo {f: 3};\n"
-"    if some_condition() {\n"
-"        let y = &x.f;      // -+ L\n"
-"        return *y;         //  |\n"
-"    }                      // -+\n"
-"    x = ~Foo {f: 4};\n"
-"    ...\n"
-"# return 0;\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:295
-msgid ""
-"Here, as before, the interior of the variable `x` is being borrowed and `x` "
-"is declared as mutable. However, the compiler can prove that `x` is not "
-"assigned anywhere in the lifetime L of the variable `y`. Therefore, it "
-"accepts the function, even though `x` is mutable and in fact is mutated "
-"later in the function."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:301
-msgid ""
-"It may not be clear why we are so concerned about mutating a borrowed "
-"variable. The reason is that the runtime system frees any owned box _as soon "
-"as its owning reference changes or goes out of scope_. Therefore, a program "
-"like this is illegal (and would be rejected by the compiler):"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:310
-#, no-wrap
-msgid ""
-"~~~ {.xfail-test}\n"
-"fn example3() -> int {\n"
-"    let mut x = ~X {f: 3};\n"
-"    let y = &x.f;\n"
-"    x = ~X {f: 4};  // Error reported here.\n"
-"    *y\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:313
-msgid ""
-"To make this clearer, consider this diagram showing the state of memory "
-"immediately before the re-assignment of `x`:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:316 doc/tutorial-borrowed-ptr.md:330
-#, no-wrap
-msgid ""
-"~~~ {.notrust}\n"
-"    Stack               Exchange Heap\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:325
-#, no-wrap
-msgid ""
-"  x +----------+\n"
-"    | ~{f:int} | ----+\n"
-"  y +----------+     |\n"
-"    | &int     | ----+\n"
-"    +----------+     |    +---------+\n"
-"                     +--> |  f: 3   |\n"
-"                          +---------+\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:327
-msgid "Once the reassignment occurs, the memory will look like this:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:339
-#, no-wrap
-msgid ""
-"  x +----------+          +---------+\n"
-"    | ~{f:int} | -------> |  f: 4   |\n"
-"  y +----------+          +---------+\n"
-"    | &int     | ----+\n"
-"    +----------+     |    +---------+\n"
-"                     +--> | (freed) |\n"
-"                          +---------+\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:342
-msgid ""
-"Here you can see that the variable `y` still points at the old box, which "
-"has been freed."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:348
-msgid ""
-"In fact, the compiler can apply the same kind of reasoning to any memory "
-"that is _(uniquely) owned by the stack frame_. So we could modify the "
-"previous example to introduce additional owned pointers and structs, and the "
-"compiler will still be able to detect possible mutations:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:353
-#, no-wrap
-msgid ""
-"~~~ {.xfail-test}\n"
-"fn example3() -> int {\n"
-"    struct R { g: int }\n"
-"    struct S { f: ~R }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:361
-#, no-wrap
-msgid ""
-"    let mut x = ~S {f: ~R {g: 3}};\n"
-"    let y = &x.f.g;\n"
-"    x = ~S {f: ~R {g: 4}};  // Error reported here.\n"
-"    x.f = ~R {g: 5};        // Error reported here.\n"
-"    *y\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:365
-msgid ""
-"In this case, two errors are reported, one when the variable `x` is modified "
-"and another when `x.f` is modified. Either modification would invalidate the "
-"pointer `y`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:367
-msgid "# Borrowing and enums"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:373
-msgid ""
-"The previous example showed that the type system forbids any borrowing of "
-"owned boxes found in aliasable, mutable memory. This restriction prevents "
-"pointers from pointing into freed memory. There is one other case where the "
-"compiler must be very careful to ensure that pointers remain valid: pointers "
-"into the interior of an `enum`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:376
-msgid ""
-"As an example, let’s look at the following `shape` type that can represent "
-"both rectangles and circles:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:385
-#, no-wrap
-msgid ""
-"~~~\n"
-"struct Point {x: float, y: float}; // as before\n"
-"struct Size {w: float, h: float}; // as before\n"
-"enum Shape {\n"
-"    Circle(Point, float),   // origin, radius\n"
-"    Rectangle(Point, Size)  // upper-left, dimensions\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:389
-msgid ""
-"Now we might write a function to compute the area of a shape. This function "
-"takes a borrowed pointer to a shape, to avoid the need for copying."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:405
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point {x: float, y: float}; // as before\n"
-"# struct Size {w: float, h: float}; // as before\n"
-"# enum Shape {\n"
-"#     Circle(Point, float),   // origin, radius\n"
-"#     Rectangle(Point, Size)  // upper-left, dimensions\n"
-"# }\n"
-"# static tau: float = 6.28f;\n"
-"fn compute_area(shape: &Shape) -> float {\n"
-"    match *shape {\n"
-"        Circle(_, radius) => 0.5 * tau * radius * radius,\n"
-"        Rectangle(_, ref size) => size.w * size.h\n"
-"    }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:410
-msgid ""
-"The first case matches against circles. Here, the pattern extracts the "
-"radius from the shape variant and the action uses it to compute the area of "
-"the circle. (Like any up-to-date engineer, we use the [tau circle constant]"
-"[tau] and not that dreadfully outdated notion of pi)."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:412
-msgid "[tau]: http://www.math.utah.edu/~palais/pi.html"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:418
-msgid ""
-"The second match is more interesting. Here we match against a rectangle and "
-"extract its size: but rather than copy the `size` struct, we use a by-"
-"reference binding to create a pointer to it. In other words, a pattern "
-"binding like `ref size` binds the name `size` to a pointer of type `&size` "
-"into the _interior of the enum_."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:421
-msgid ""
-"To make this more clear, let's look at a diagram of memory layout in the "
-"case where `shape` points at a rectangle:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:424 doc/tutorial-borrowed-ptr.md:449
-#, no-wrap
-msgid ""
-"~~~ {.notrust}\n"
-"Stack             Memory\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:433
-#, no-wrap
-msgid ""
-"+-------+         +---------------+\n"
-"| shape | ------> | rectangle(    |\n"
-"+-------+         |   {x: float,  |\n"
-"| size  | -+      |    y: float}, |\n"
-"+-------+  +----> |   {w: float,  |\n"
-"                  |    h: float}) |\n"
-"                  +---------------+\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:440
-msgid ""
-"Here you can see that rectangular shapes are composed of five words of "
-"memory. The first is a tag indicating which variant this enum is "
-"(`rectangle`, in this case). The next two words are the `x` and `y` fields "
-"for the point and the remaining two are the `w` and `h` fields for the size. "
-"The binding `size` is then a pointer into the inside of the shape."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:446
-msgid ""
-"Perhaps you can see where the danger lies: if the shape were somehow to be "
-"reassigned, perhaps to a circle, then although the memory used to store that "
-"shape value would still be valid, _it would have a different type_! The "
-"following diagram shows what memory would look like if code overwrote "
-"`shape` with a circle:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:458
-#, no-wrap
-msgid ""
-"+-------+         +---------------+\n"
-"| shape | ------> | circle(       |\n"
-"+-------+         |   {x: float,  |\n"
-"| size  | -+      |    y: float}, |\n"
-"+-------+  +----> |   float)      |\n"
-"                  |               |\n"
-"                  +---------------+\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:463
-msgid ""
-"As you can see, the `size` pointer would be pointing at a `float` instead of "
-"a struct. This is not good: dereferencing the second field of a `float` as "
-"if it were a struct with two fields would be a memory safety violation."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:475
-msgid ""
-"So, in fact, for every `ref` binding, the compiler will impose the same "
-"rules as the ones we saw for borrowing the interior of a owned box: it must "
-"be able to guarantee that the `enum` will not be overwritten for the "
-"duration of the borrow.  In fact, the compiler would accept the example we "
-"gave earlier. The example is safe because the shape pointer has type "
-"`&Shape`, which means \"borrowed pointer to immutable memory containing a "
-"`shape`\". If, however, the type of that pointer were `&mut Shape`, then the "
-"ref binding would be ill-typed.  Just as with owned boxes, the compiler will "
-"permit `ref` bindings into data owned by the stack frame even if the data "
-"are mutable, but otherwise it requires that the data reside in immutable "
-"memory."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:477
-msgid "# Returning borrowed pointers"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:483
-msgid ""
-"So far, all of the examples we have looked at, use borrowed pointers in a "
-"“downward” direction. That is, a method or code block creates a borrowed "
-"pointer, then uses it within the same scope. It is also possible to return "
-"borrowed pointers as the result of a function, but as we'll see, doing so "
-"requires some explicit annotation."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:485
-msgid "For example, we could write a subroutine like this:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:490
-msgid ""
-"~~~ struct Point {x: float, y: float} fn get_x<'r>(p: &'r Point) -> &'r "
-"float { &p.x } ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:498
-msgid ""
-"Here, the function `get_x()` returns a pointer into the structure it was "
-"given. The type of the parameter (`&'r Point`) and return type (`&'r float`) "
-"both use a new syntactic form that we have not seen so far.  Here the "
-"identifier `r` names the lifetime of the pointer explicitly. So in effect, "
-"this function declares that it takes a pointer with lifetime `r` and returns "
-"a pointer with that same lifetime."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:504
-msgid ""
-"In general, it is only possible to return borrowed pointers if they are "
-"derived from a parameter to the procedure. In that case, the pointer result "
-"will always have the same lifetime as one of the parameters; named lifetimes "
-"indicate which parameter that is."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:510
-msgid ""
-"In the previous examples, function parameter types did not include a "
-"lifetime name. In those examples, the compiler simply creates a fresh name "
-"for the lifetime automatically: that is, the lifetime name is guaranteed to "
-"refer to a distinct lifetime from the lifetimes of all other parameters."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:518
-msgid ""
-"Named lifetimes that appear in function signatures are conceptually the same "
-"as the other lifetimes we have seen before, but they are a bit abstract: "
-"they don’t refer to a specific expression within `get_x()`, but rather to "
-"some expression within the *caller of `get_x()`*.  The lifetime `r` is "
-"actually a kind of *lifetime parameter*: it is defined by the caller to "
-"`get_x()`, just as the value for the parameter `p` is defined by that caller."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:523
-msgid ""
-"In any case, whatever the lifetime of `r` is, the pointer produced by `&p.x` "
-"always has the same lifetime as `p` itself: a pointer to a field of a struct "
-"is valid as long as the struct is valid. Therefore, the compiler accepts the "
-"function `get_x()`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:526
-msgid ""
-"To emphasize this point, let’s look at a variation on the example, this time "
-"one that does not compile:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:533
-#, no-wrap
-msgid ""
-"~~~ {.xfail-test}\n"
-"struct Point {x: float, y: float}\n"
-"fn get_x_sh(p: @Point) -> &float {\n"
-"    &p.x // Error reported here\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:541
-msgid ""
-"Here, the function `get_x_sh()` takes a managed box as input and returns a "
-"borrowed pointer. As before, the lifetime of the borrowed pointer that will "
-"be returned is a parameter (specified by the caller). That means that "
-"`get_x_sh()` promises to return a borrowed pointer that is valid for as long "
-"as the caller would like: this is subtly different from the first example, "
-"which promised to return a pointer that was valid for as long as its pointer "
-"argument was valid."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:552
-msgid ""
-"Within `get_x_sh()`, we see the expression `&p.x` which takes the address of "
-"a field of a managed box. The presence of this expression implies that the "
-"compiler must guarantee that, so long as the resulting pointer is valid, the "
-"managed box will not be reclaimed by the garbage collector. But recall that "
-"`get_x_sh()` also promised to return a pointer that was valid for as long as "
-"the caller wanted it to be. Clearly, `get_x_sh()` is not in a position to "
-"make both of these guarantees; in fact, it cannot guarantee that the pointer "
-"will remain valid at all once it returns, as the parameter `p` may or may "
-"not be live in the caller. Therefore, the compiler will report an error here."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:559
-msgid ""
-"In general, if you borrow a managed (or owned) box to create a borrowed "
-"pointer, the pointer will only be valid within the function and cannot be "
-"returned. This is why the typical way to return borrowed pointers is to take "
-"borrowed pointers as input (the only other case in which it can be legal to "
-"return a borrowed pointer is if the pointer points at a static constant)."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:561
-msgid "# Named lifetimes"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:565
-msgid ""
-"Let's look at named lifetimes in more detail. Named lifetimes allow for "
-"grouping of parameters by lifetime. For example, consider this function:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:579
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point {x: float, y: float}; // as before\n"
-"# struct Size {w: float, h: float}; // as before\n"
-"# enum Shape {\n"
-"#     Circle(Point, float),   // origin, radius\n"
-"#     Rectangle(Point, Size)  // upper-left, dimensions\n"
-"# }\n"
-"# fn compute_area(shape: &Shape) -> float { 0f }\n"
-"fn select<'r, T>(shape: &'r Shape, threshold: float,\n"
-"                 a: &'r T, b: &'r T) -> &'r T {\n"
-"    if compute_area(shape) > threshold {a} else {b}\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:585
-msgid ""
-"This function takes three borrowed pointers and assigns each the same "
-"lifetime `r`.  In practice, this means that, in the caller, the lifetime `r` "
-"will be the *intersection of the lifetime of the three region parameters*. "
-"This may be overly conservative, as in this example:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:607
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point {x: float, y: float}; // as before\n"
-"# struct Size {w: float, h: float}; // as before\n"
-"# enum Shape {\n"
-"#     Circle(Point, float),   // origin, radius\n"
-"#     Rectangle(Point, Size)  // upper-left, dimensions\n"
-"# }\n"
-"# fn compute_area(shape: &Shape) -> float { 0f }\n"
-"# fn select<'r, T>(shape: &Shape, threshold: float,\n"
-"#                  a: &'r T, b: &'r T) -> &'r T {\n"
-"#     if compute_area(shape) > threshold {a} else {b}\n"
-"# }\n"
-"                                                     // -+ r\n"
-"fn select_based_on_unit_circle<'r, T>(               //  |-+ B\n"
-"    threshold: float, a: &'r T, b: &'r T) -> &'r T { //  | |\n"
-"                                                     //  | |\n"
-"    let shape = Circle(Point {x: 0., y: 0.}, 1.);    //  | |\n"
-"    select(&shape, threshold, a, b)                  //  | |\n"
-"}                                                    //  |-+\n"
-"                                                     // -+\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:617
-msgid ""
-"In this call to `select()`, the lifetime of the first parameter shape is B, "
-"the function body. Both of the second two parameters `a` and `b` share the "
-"same lifetime, `r`, which is a lifetime parameter of "
-"`select_based_on_unit_circle()`. The caller will infer the intersection of "
-"these two lifetimes as the lifetime of the returned value, and hence the "
-"return value of `select()` will be assigned a lifetime of B. This will in "
-"turn lead to a compilation error, because `select_based_on_unit_circle()` is "
-"supposed to return a value with the lifetime `r`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:622
-msgid ""
-"To address this, we can modify the definition of `select()` to distinguish "
-"the lifetime of the first parameter from the lifetime of the latter two. "
-"After all, the first parameter is not being returned. Here is how the new "
-"`select()` might look:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:636
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point {x: float, y: float}; // as before\n"
-"# struct Size {w: float, h: float}; // as before\n"
-"# enum Shape {\n"
-"#     Circle(Point, float),   // origin, radius\n"
-"#     Rectangle(Point, Size)  // upper-left, dimensions\n"
-"# }\n"
-"# fn compute_area(shape: &Shape) -> float { 0f }\n"
-"fn select<'r, 'tmp, T>(shape: &'tmp Shape, threshold: float,\n"
-"                       a: &'r T, b: &'r T) -> &'r T {\n"
-"    if compute_area(shape) > threshold {a} else {b}\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:641
-msgid ""
-"Here you can see that `shape`'s lifetime is now named `tmp`. The parameters "
-"`a`, `b`, and the return value all have the lifetime `r`.  However, since "
-"the lifetime `tmp` is not returned, it would be more concise to just omit "
-"the named lifetime for `shape` altogether:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:655
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point {x: float, y: float}; // as before\n"
-"# struct Size {w: float, h: float}; // as before\n"
-"# enum Shape {\n"
-"#     Circle(Point, float),   // origin, radius\n"
-"#     Rectangle(Point, Size)  // upper-left, dimensions\n"
-"# }\n"
-"# fn compute_area(shape: &Shape) -> float { 0f }\n"
-"fn select<'r, T>(shape: &Shape, threshold: float,\n"
-"                 a: &'r T, b: &'r T) -> &'r T {\n"
-"    if compute_area(shape) > threshold {a} else {b}\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:657
-msgid "This is equivalent to the previous definition."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:659
-msgid "# Conclusion"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-borrowed-ptr.md:663
-msgid ""
-"So there you have it: a (relatively) brief tour of the borrowed pointer "
-"system. For more details, we refer to the (yet to be written) reference "
-"document on borrowed pointers, which will explain the full notation and give "
-"more examples."
-msgstr ""
diff --git a/doc/po/ja/tutorial-container.md.po b/doc/po/ja/tutorial-container.md.po
deleted file mode 100644 (file)
index 0251341..0000000
+++ /dev/null
@@ -1,673 +0,0 @@
-# Japanese translations for Rust package
-# Copyright (C) 2013 The Rust Project Developers
-# This file is distributed under the same license as the Rust package.
-# Automatically generated, 2013.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Rust 0.8\n"
-"POT-Creation-Date: 2013-08-05 19:40+0900\n"
-"PO-Revision-Date: 2013-07-28 20:32+0900\n"
-"Last-Translator: Automatically generated\n"
-"Language-Team: none\n"
-"Language: ja\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. type: Plain text
-#: doc/tutorial-container.md:2
-msgid "% Containers and iterators"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:4
-msgid "# Containers"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:6
-msgid "The container traits are defined in the `std::container` module."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:8
-msgid "## Unique and managed vectors"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:12
-msgid ""
-"Vectors have `O(1)` indexing and removal from the end, along with `O(1)` "
-"amortized insertion. Vectors are the most common container in Rust, and are "
-"flexible enough to fit many use cases."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:16
-msgid ""
-"Vectors can also be sorted and used as efficient lookup tables with the "
-"`std::vec::bsearch` function, if all the elements are inserted at one time "
-"and deletions are unnecessary."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:18
-msgid "## Maps and sets"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:22
-msgid ""
-"Maps are collections of unique keys with corresponding values, and sets are "
-"just unique keys without a corresponding value. The `Map` and `Set` traits "
-"in `std::container` define the basic interface."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:24
-msgid "The standard library provides three owned map/set types:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-container.md:30
-msgid ""
-"`std::hashmap::HashMap` and `std::hashmap::HashSet`, requiring the keys to "
-"implement `Eq` and `Hash`"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-container.md:30
-msgid ""
-"`std::trie::TrieMap` and `std::trie::TrieSet`, requiring the keys to be "
-"`uint`"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-container.md:30
-msgid ""
-"`extra::treemap::TreeMap` and `extra::treemap::TreeSet`, requiring the keys "
-"to implement `TotalOrd`"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:34
-msgid ""
-"These maps do not use managed pointers so they can be sent between tasks as "
-"long as the key and value types are sendable. Neither the key or value type "
-"has to be copyable."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:37
-msgid ""
-"The `TrieMap` and `TreeMap` maps are ordered, while `HashMap` uses an "
-"arbitrary order."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:42
-msgid ""
-"Each `HashMap` instance has a random 128-bit key to use with a keyed hash, "
-"making the order of a set of keys in a given hash table randomized. Rust "
-"provides a [SipHash](https://131002.net/siphash/) implementation for any "
-"type implementing the `IterBytes` trait."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:44
-msgid "## Double-ended queues"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:49
-msgid ""
-"The `extra::deque` module implements a double-ended queue with `O(1)` "
-"amortized inserts and removals from both ends of the container. It also has "
-"`O(1)` indexing like a vector. The contained elements are not required to be "
-"copyable, and the queue will be sendable if the contained type is sendable."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:51
-msgid "## Priority queues"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:55
-msgid ""
-"The `extra::priority_queue` module implements a queue ordered by a key.  The "
-"contained elements are not required to be copyable, and the queue will be "
-"sendable if the contained type is sendable."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:61
-msgid ""
-"Insertions have `O(log n)` time complexity and checking or popping the "
-"largest element is `O(1)`. Converting a vector to a priority queue can be "
-"done in-place, and has `O(n)` complexity. A priority queue can also be "
-"converted to a sorted vector in-place, allowing it to be used for an `O(n "
-"log n)` in-place heapsort."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:63
-msgid "# Iterators"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:65
-msgid "## Iteration protocol"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:69
-msgid ""
-"The iteration protocol is defined by the `Iterator` trait in the `std::"
-"iterator` module. The minimal implementation of the trait is a `next` "
-"method, yielding the next element from an iterator object:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:73
-msgid "~~~ /// An infinite stream of zeroes struct ZeroStream;"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:80
-#, no-wrap
-msgid ""
-"impl Iterator<int> for ZeroStream {\n"
-"    fn next(&mut self) -> Option<int> {\n"
-"        Some(0)\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:83
-msgid ""
-"Reaching the end of the iterator is signalled by returning `None` instead of "
-"`Some(item)`:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:89 doc/tutorial-container.md:262
-#, no-wrap
-msgid ""
-"~~~\n"
-"/// A stream of N zeroes\n"
-"struct ZeroStream {\n"
-"    priv remaining: uint\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:95
-#, no-wrap
-msgid ""
-"impl ZeroStream {\n"
-"    fn new(n: uint) -> ZeroStream {\n"
-"        ZeroStream { remaining: n }\n"
-"    }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:107 doc/tutorial-container.md:284
-#, no-wrap
-msgid ""
-"impl Iterator<int> for ZeroStream {\n"
-"    fn next(&mut self) -> Option<int> {\n"
-"        if self.remaining == 0 {\n"
-"            None\n"
-"        } else {\n"
-"            self.remaining -= 1;\n"
-"            Some(0)\n"
-"        }\n"
-"    }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:109
-msgid "## Container iterators"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:112
-msgid ""
-"Containers implement iteration over the contained elements by returning an "
-"iterator object. For example, vector slices several iterators available:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-container.md:116
-msgid "`iter()` and `rev_iter()`, for immutable references to the elements"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-container.md:116
-msgid ""
-"`mut_iter()` and `mut_rev_iter()`, for mutable references to the elements"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-container.md:116
-msgid ""
-"`consume_iter()` and `consume_rev_iter`, to move the elements out by-value"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:119
-msgid ""
-"A typical mutable container will implement at least `iter()`, `mut_iter()` "
-"and `consume_iter()` along with the reverse variants if it maintains an "
-"order."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:121
-msgid "### Freezing"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:125
-msgid ""
-"Unlike most other languages with external iterators, Rust has no *iterator "
-"invalidation*. As long an iterator is still in scope, the compiler will "
-"prevent modification of the container through another handle."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:130
-#, no-wrap
-msgid ""
-"~~~\n"
-"let mut xs = [1, 2, 3];\n"
-"{\n"
-"    let _it = xs.iter();\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:136
-#, no-wrap
-msgid ""
-"    // the vector is frozen for this scope, the compiler will statically\n"
-"    // prevent modification\n"
-"}\n"
-"// the vector becomes unfrozen again at the end of the scope\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:139
-msgid ""
-"These semantics are due to most container iterators being implemented with "
-"`&` and `&mut`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:141
-msgid "## Iterator adaptors"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:145
-msgid ""
-"The `IteratorUtil` trait implements common algorithms as methods extending "
-"every `Iterator` implementation. For example, the `fold` method will "
-"accumulate the items yielded by an `Iterator` into a single value:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:151
-msgid ""
-"~~~ let xs = [1, 9, 2, 3, 14, 12]; let result = xs.iter().fold(0, |"
-"accumulator, item| accumulator - *item); assert_eq!(result, -41); ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:153
-msgid ""
-"Some adaptors return an adaptor object implementing the `Iterator` trait "
-"itself:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:160
-msgid ""
-"~~~ let xs = [1, 9, 2, 3, 14, 12]; let ys = [5, 2, 1, 8]; let sum = xs."
-"iter().chain_(ys.iter()).fold(0, |a, b| a + *b); assert_eq!(sum, 57); ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:164
-msgid ""
-"Note that some adaptors like the `chain_` method above use a trailing "
-"underscore to work around an issue with method resolve. The underscores will "
-"be dropped when they become unnecessary."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:166
-msgid "## For loops"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:168
-msgid ""
-"The `for` keyword can be used as sugar for iterating through any iterator:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:171
-msgid "~~~ let xs = [2, 3, 5, 7, 11, 13, 17];"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:176
-#, no-wrap
-msgid ""
-"// print out all the elements in the vector\n"
-"for x in xs.iter() {\n"
-"    println(x.to_str())\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:182
-#, no-wrap
-msgid ""
-"// print out all but the first 3 elements in the vector\n"
-"for x in xs.iter().skip(3) {\n"
-"    println(x.to_str())\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:185
-msgid ""
-"For loops are *often* used with a temporary iterator object, as above. They "
-"can also advance the state of an iterator in a mutable location:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:189
-msgid ""
-"~~~ let xs = [1, 2, 3, 4, 5]; let ys = [\"foo\", \"bar\", \"baz\", \"foobar"
-"\"];"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:192
-msgid ""
-"// create an iterator yielding tuples of elements from both vectors let mut "
-"it = xs.iter().zip(ys.iter());"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:196
-#, no-wrap
-msgid ""
-"// print out the pairs of elements up to (&3, &\"baz\")\n"
-"for (x, y) in it {\n"
-"    printfln!(\"%d %s\", *x, *y);\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:201
-#, no-wrap
-msgid ""
-"    if *x == 3 {\n"
-"        break;\n"
-"    }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:204
-msgid ""
-"// yield and print the last pair from the iterator printfln!(\"last: %?\", "
-"it.next());"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:208
-msgid "// the iterator is now fully consumed assert!(it.next().is_none()); ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:210
-msgid "## Conversion"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:212
-msgid ""
-"Iterators offer generic conversion to containers with the `collect` adaptor:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:218
-msgid ""
-"~~~ let xs = [0, 1, 1, 2, 3, 5, 8]; let ys = xs.rev_iter().skip(1)."
-"transform(|&x| x * 2).collect::<~[int]>(); assert_eq!(ys, ~[10, 6, 4, 2, 2, "
-"0]); ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:221
-msgid ""
-"The method requires a type hint for the container type, if the surrounding "
-"code does not provide sufficient information."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:225
-msgid ""
-"Containers can provide conversion from iterators through `collect` by "
-"implementing the `FromIterator` trait. For example, the implementation for "
-"vectors is as follows:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:238
-#, no-wrap
-msgid ""
-"~~~\n"
-"impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {\n"
-"    pub fn from_iterator(iterator: &mut T) -> ~[A] {\n"
-"        let (lower, _) = iterator.size_hint();\n"
-"        let mut xs = with_capacity(lower);\n"
-"        for x in iterator {\n"
-"            xs.push(x);\n"
-"        }\n"
-"        xs\n"
-"    }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:240
-msgid "### Size hints"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:243
-msgid ""
-"The `Iterator` trait provides a `size_hint` default method, returning a "
-"lower bound and optionally on upper bound on the length of the iterator:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:247
-msgid "~~~ fn size_hint(&self) -> (uint, Option<uint>) { (0, None) } ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:251
-msgid ""
-"The vector implementation of `FromIterator` from above uses the lower bound "
-"to pre-allocate enough space to hold the minimum number of elements the "
-"iterator will yield."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:254
-msgid ""
-"The default implementation is always correct, but it should be overridden if "
-"the iterator can provide better information."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:256
-msgid ""
-"The `ZeroStream` from earlier can provide an exact lower and upper bound:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:267
-#, no-wrap
-msgid ""
-"impl ZeroStream {\n"
-"    fn new(n: uint) -> ZeroStream {\n"
-"        ZeroStream { remaining: n }\n"
-"    }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:272
-#, no-wrap
-msgid ""
-"    fn size_hint(&self) -> (uint, Option<uint>) {\n"
-"        (self.remaining, Some(self.remaining))\n"
-"    }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:286
-msgid "## Double-ended iterators"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:290
-msgid ""
-"The `DoubleEndedIterator` trait represents an iterator able to yield "
-"elements from either end of a range. It inherits from the `Iterator` trait "
-"and extends it with the `next_back` function."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:293
-msgid ""
-"A `DoubleEndedIterator` can be flipped with the `invert` adaptor, returning "
-"another `DoubleEndedIterator` with `next` and `next_back` exchanged."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:300
-msgid ""
-"~~~ let xs = [1, 2, 3, 4, 5, 6]; let mut it = xs.iter(); printfln!(\"%?\", "
-"it.next()); // prints `Some(&1)` printfln!(\"%?\", it.next()); // prints "
-"`Some(&2)` printfln!(\"%?\", it.next_back()); // prints `Some(&6)`"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:306
-#, no-wrap
-msgid ""
-"// prints `5`, `4` and `3`\n"
-"for &x in it.invert() {\n"
-"    printfln!(\"%?\", x)\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:309
-msgid ""
-"The `rev_iter` and `mut_rev_iter` methods on vectors just return an inverted "
-"version of the standard immutable and mutable vector iterators."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:312
-msgid ""
-"The `chain_`, `transform`, `filter`, `filter_map` and `peek` adaptors are "
-"`DoubleEndedIterator` implementations if the underlying iterators are."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:317
-msgid ""
-"~~~ let xs = [1, 2, 3, 4]; let ys = [5, 6, 7, 8]; let mut it = xs.iter()."
-"chain_(ys.iter()).transform(|&x| x * 2);"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:319
-msgid "printfln!(\"%?\", it.next()); // prints `Some(2)`"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:325
-#, no-wrap
-msgid ""
-"// prints `16`, `14`, `12`, `10`, `8`, `6`, `4`\n"
-"for x in it.invert() {\n"
-"    printfln!(\"%?\", x);\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:327
-msgid "## Random-access iterators"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:331
-msgid ""
-"The `RandomAccessIterator` trait represents an iterator offering random "
-"access to the whole range. The `indexable` method retrieves the number of "
-"elements accessible with the `idx` method."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:334
-msgid ""
-"The `chain_` adaptor is an implementation of `RandomAccessIterator` if the "
-"underlying iterators are."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:343
-msgid ""
-"~~~ let xs = [1, 2, 3, 4, 5]; let ys = ~[7, 9, 11]; let mut it = xs.iter()."
-"chain_(ys.iter()); printfln!(\"%?\", it.idx(0)); // prints `Some(&1)` "
-"printfln!(\"%?\", it.idx(5)); // prints `Some(&7)` printfln!(\"%?\", it."
-"idx(7)); // prints `Some(&11)` printfln!(\"%?\", it.idx(8)); // prints `None`"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:348
-msgid ""
-"// yield two elements from the beginning, and one from the end it.next(); it."
-"next(); it.next_back();"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-container.md:352
-msgid ""
-"printfln!(\"%?\", it.idx(0)); // prints `Some(&3)` printfln!(\"%?\", it."
-"idx(4)); // prints `Some(&9)` printfln!(\"%?\", it.idx(6)); // prints `None` "
-"~~~"
-msgstr ""
diff --git a/doc/po/ja/tutorial-ffi.md.po b/doc/po/ja/tutorial-ffi.md.po
deleted file mode 100644 (file)
index 088970b..0000000
+++ /dev/null
@@ -1,602 +0,0 @@
-# Japanese translations for Rust package
-# Copyright (C) 2013 The Rust Project Developers
-# This file is distributed under the same license as the Rust package.
-# Automatically generated, 2013.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Rust 0.8\n"
-"POT-Creation-Date: 2013-08-10 07:44+0900\n"
-"PO-Revision-Date: 2013-07-22 23:37+0900\n"
-"Last-Translator: Automatically generated\n"
-"Language-Team: none\n"
-"Language: ja\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. type: Plain text
-#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
-#: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
-#: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
-msgid "# Introduction"
-msgstr "# イントロダクション"
-
-#. type: Plain text
-#: doc/tutorial.md:868 doc/tutorial-ffi.md:143
-msgid "# Destructors"
-msgstr "# デストラクタ"
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:2
-msgid "% Rust Foreign Function Interface Tutorial"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:10
-msgid ""
-"This tutorial will use the [snappy](https://code.google.com/p/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://code."
-"google.com/p/snappy/source/browse/trunk/snappy-c.h))."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:13
-msgid ""
-"The following is a minimal example of calling a foreign function which will "
-"compile if snappy is installed:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:16
-msgid "~~~~ {.xfail-test} use std::libc::size_t;"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:21
-#, no-wrap
-msgid ""
-"#[link_args = \"-lsnappy\"]\n"
-"extern {\n"
-"    fn snappy_max_compressed_length(source_length: size_t) -> size_t;\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:27
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"    let x = unsafe { snappy_max_compressed_length(100) };\n"
-"    println(fmt!(\"max compressed length of a 100 byte buffer: %?\", x));\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:31
-msgid ""
-"The `extern` block is a list of function signatures in a foreign library, in "
-"this case with the platform's C ABI. The `#[link_args]` attribute is used to "
-"instruct the linker to link against the snappy library so the symbols are "
-"resolved."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:37
-msgid ""
-"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."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:41
-msgid ""
-"When declaring the argument types to a foreign function, the Rust compiler "
-"will not check if the declaration is correct, so specifying it correctly is "
-"part of keeping the binding correct at runtime."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:43
-msgid "The `extern` block can be extended to cover the entire snappy API:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:46
-msgid "~~~~ {.xfail-test} use std::libc::{c_int, size_t};"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:65
-#, no-wrap
-msgid ""
-"#[link_args = \"-lsnappy\"]\n"
-"extern {\n"
-"    fn snappy_compress(input: *u8,\n"
-"                       input_length: size_t,\n"
-"                       compressed: *mut u8,\n"
-"                       compressed_length: *mut size_t) -> c_int;\n"
-"    fn snappy_uncompress(compressed: *u8,\n"
-"                         compressed_length: size_t,\n"
-"                         uncompressed: *mut u8,\n"
-"                         uncompressed_length: *mut size_t) -> c_int;\n"
-"    fn snappy_max_compressed_length(source_length: size_t) -> size_t;\n"
-"    fn snappy_uncompressed_length(compressed: *u8,\n"
-"                                  compressed_length: size_t,\n"
-"                                  result: *mut size_t) -> c_int;\n"
-"    fn snappy_validate_compressed_buffer(compressed: *u8,\n"
-"                                         compressed_length: size_t) -> c_int;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:67
-msgid "# Creating a safe interface"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:71
-msgid ""
-"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."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:76
-msgid ""
-"Wrapping the functions which expect buffers involves using the `vec::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 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."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:84
-#, no-wrap
-msgid ""
-"~~~~ {.xfail-test}\n"
-"pub fn validate_compressed_buffer(src: &[u8]) -> bool {\n"
-"    unsafe {\n"
-"        snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:88
-msgid ""
-"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."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:91
-msgid ""
-"The `snappy_compress` and `snappy_uncompress` functions are more complex, "
-"since a buffer has to be allocated to hold the output too."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:96
-msgid ""
-"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."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:102
-#, no-wrap
-msgid ""
-"~~~~ {.xfail-test}\n"
-"pub fn compress(src: &[u8]) -> ~[u8] {\n"
-"    unsafe {\n"
-"        let srclen = src.len() as size_t;\n"
-"        let psrc = src.as_ptr();\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:106
-#, no-wrap
-msgid ""
-"        let mut dstlen = snappy_max_compressed_length(srclen);\n"
-"        let mut dst = vec::with_capacity(dstlen as uint);\n"
-"        let pdst = dst.as_mut_ptr();\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:113
-#, no-wrap
-msgid ""
-"        snappy_compress(psrc, srclen, pdst, &mut dstlen);\n"
-"        dst.set_len(dstlen as uint);\n"
-"        dst\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:116
-msgid ""
-"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."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:122
-#, no-wrap
-msgid ""
-"~~~~ {.xfail-test}\n"
-"pub fn uncompress(src: &[u8]) -> Option<~[u8]> {\n"
-"    unsafe {\n"
-"        let srclen = src.len() as size_t;\n"
-"        let psrc = src.as_ptr();\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:125
-#, no-wrap
-msgid ""
-"        let mut dstlen: size_t = 0;\n"
-"        snappy_uncompressed_length(psrc, srclen, &mut dstlen);\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:128
-#, no-wrap
-msgid ""
-"        let mut dst = vec::with_capacity(dstlen as uint);\n"
-"        let pdst = dst.as_mut_ptr();\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:138
-#, no-wrap
-msgid ""
-"        if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {\n"
-"            dst.set_len(dstlen as uint);\n"
-"            Some(dst)\n"
-"        } else {\n"
-"            None // SNAPPY_INVALID_INPUT\n"
-"        }\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:141
-msgid ""
-"For reference, the examples used here are also available as an [library on "
-"GitHub](https://github.com/thestinger/rust-snappy)."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:147
-msgid ""
-"Foreign libraries often hand off ownership of resources to the calling code, "
-"which should be wrapped in a destructor to provide safety and guarantee "
-"their release."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:150
-msgid ""
-"A type with the same functionality as owned boxes can be implemented by "
-"wrapping `malloc` and `free`:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:156
-msgid ""
-"~~~~ use std::cast; use std::libc::{c_void, size_t, malloc, free}; use std::"
-"ptr; use std::unstable::intrinsics;"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:161
-#, no-wrap
-msgid ""
-"// a wrapper around the handle returned by the foreign code\n"
-"pub struct Unique<T> {\n"
-"    priv ptr: *mut T\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:172
-#, no-wrap
-msgid ""
-"impl<T: Send> Unique<T> {\n"
-"    pub fn new(value: T) -> Unique<T> {\n"
-"        unsafe {\n"
-"            let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;\n"
-"            assert!(!ptr::is_null(ptr));\n"
-"            // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it\n"
-"            intrinsics::move_val_init(&mut *ptr, value);\n"
-"            Unique{ptr: ptr}\n"
-"        }\n"
-"    }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:177
-#, no-wrap
-msgid ""
-"    // the 'r lifetime results in the same semantics as `&*x` with ~T\n"
-"    pub fn borrow<'r>(&'r self) -> &'r T {\n"
-"        unsafe { cast::copy_lifetime(self, &*self.ptr) }\n"
-"    }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:183
-#, no-wrap
-msgid ""
-"    // the 'r lifetime results in the same semantics as `&mut *x` with ~T\n"
-"    pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T {\n"
-"        unsafe { cast::copy_mut_lifetime(self, &mut *self.ptr) }\n"
-"    }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:195
-#, no-wrap
-msgid ""
-"#[unsafe_destructor]\n"
-"impl<T: Send> Drop for Unique<T> {\n"
-"    fn drop(&self) {\n"
-"        unsafe {\n"
-"            let x = intrinsics::init(); // dummy value to swap in\n"
-"            // moving the object out is needed to call the destructor\n"
-"            ptr::replace_ptr(self.ptr, x);\n"
-"            free(self.ptr as *c_void)\n"
-"        }\n"
-"    }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:202
-#, no-wrap
-msgid ""
-"// A comparison between the built-in ~ and this reimplementation\n"
-"fn main() {\n"
-"    {\n"
-"        let mut x = ~5;\n"
-"        *x = 10;\n"
-"    } // `x` is freed here\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:209
-#, no-wrap
-msgid ""
-"    {\n"
-"        let mut y = Unique::new(5);\n"
-"        *y.borrow_mut() = 10;\n"
-"    } // `y` is freed here\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:211
-msgid "# Linking"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:215
-msgid ""
-"In addition to the `#[link_args]` attribute for explicitly passing arguments "
-"to the linker, an `extern mod` block will pass `-lmodname` to the linker by "
-"default unless it has a `#[nolink]` attribute applied."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:217
-msgid "# Unsafe blocks"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:221
-msgid ""
-"Some operations, like dereferencing unsafe 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."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:224
-msgid ""
-"Unsafe functions, on the other hand, advertise it to the world. An unsafe "
-"function is written like this:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:228
-msgid "~~~~ unsafe fn kaboom(ptr: *int) -> int { *ptr } ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:230
-msgid ""
-"This function can only be called from an `unsafe` block or another `unsafe` "
-"function."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:232
-msgid "# Accessing foreign globals"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:236
-msgid ""
-"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:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:239
-msgid "~~~{.xfail-test} use std::libc;"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:244
-#, no-wrap
-msgid ""
-"#[link_args = \"-lreadline\"]\n"
-"extern {\n"
-"    static rl_readline_version: libc::c_int;\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:250
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"    println(fmt!(\"You have readline version %d installed.\",\n"
-"                 rl_readline_version as int));\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:254
-msgid ""
-"Alternatively, you may need to alter global state provided by a foreign "
-"interface. To do this, statics can be declared with `mut` so rust can mutate "
-"them."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:258
-msgid "~~~{.xfail-test} use std::libc; use std::ptr;"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:263
-#, no-wrap
-msgid ""
-"#[link_args = \"-lreadline\"]\n"
-"extern {\n"
-"    static mut rl_prompt: *libc::c_char;\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:272
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"    do \"[my-awesome-shell] $\".as_c_str |buf| {\n"
-"        unsafe { rl_prompt = buf; }\n"
-"        // get a line, process it\n"
-"        unsafe { rl_prompt = ptr::null(); }\n"
-"    }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:274
-msgid "# Foreign calling conventions"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:279
-msgid ""
-"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 the `abi` attribute as a way to hint to the compiler which calling "
-"convention to use:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:288
-#, no-wrap
-msgid ""
-"~~~~\n"
-"#[cfg(target_os = \"win32\")]\n"
-"#[abi = \"stdcall\"]\n"
-"#[link_name = \"kernel32\"]\n"
-"extern {\n"
-"    fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:292
-msgid ""
-"The `abi` attribute applies to a foreign module (it cannot be applied to a "
-"single function within a module), and must be either `\"cdecl\"` or `"
-"\"stdcall\"`. The compiler may eventually support other calling conventions."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:294
-msgid "# Interoperability with foreign code"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:298
-msgid ""
-"Rust guarantees that the layout of a `struct` is compatible with the "
-"platform's representation in C.  A `#[packed]` attribute is available, which "
-"will lay out the struct members without padding.  However, there are "
-"currently no guarantees about the layout of an `enum`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:305
-msgid ""
-"Rust's owned and managed boxes 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. Borrowed pointers 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."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:310
-msgid ""
-"Vectors and strings share the same basic memory layout, and utilities are "
-"available in the `vec` and `str` modules for working with C APIs. Strings "
-"are terminated with `\\0` for interoperability with C, but it should not be "
-"assumed because a slice will not always be nul-terminated. Instead, the "
-"`str::as_c_str` function should be used."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-ffi.md:312
-msgid ""
-"The standard library includes type aliases and function definitions for the "
-"C standard library in the `libc` module, and Rust links against `libc` and "
-"`libm` by default."
-msgstr ""
diff --git a/doc/po/ja/tutorial-macros.md.po b/doc/po/ja/tutorial-macros.md.po
deleted file mode 100644 (file)
index a7704bc..0000000
+++ /dev/null
@@ -1,683 +0,0 @@
-# Japanese translations for Rust package
-# Copyright (C) 2013 The Rust Project Developers
-# This file is distributed under the same license as the Rust package.
-# Automatically generated, 2013.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Rust 0.8\n"
-"POT-Creation-Date: 2013-07-28 20:32+0900\n"
-"PO-Revision-Date: 2013-07-28 20:32+0900\n"
-"Last-Translator: Automatically generated\n"
-"Language-Team: none\n"
-"Language: ja\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. type: Plain text
-#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
-#: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
-#: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
-msgid "# Introduction"
-msgstr "# イントロダクション"
-
-#. type: Plain text
-#: doc/rust.md:2136 doc/rust.md:2223 doc/tutorial-macros.md:323
-msgid "~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:2
-msgid "% Rust Macros Tutorial"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:12
-msgid ""
-"Functions are the primary tool that programmers can use to build "
-"abstractions.  Sometimes, however, programmers want to abstract over compile-"
-"time syntax rather than run-time values.  Macros provide syntactic "
-"abstraction.  For an example of how this can be useful, consider the "
-"following two code fragments, which both pattern-match on their input and "
-"both return early in one case, doing nothing otherwise:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:30
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# enum t { special_a(uint), special_b(uint) };\n"
-"# fn f() -> uint {\n"
-"# let input_1 = special_a(0);\n"
-"# let input_2 = special_a(0);\n"
-"match input_1 {\n"
-"    special_a(x) => { return x; }\n"
-"    _ => {}\n"
-"}\n"
-"// ...\n"
-"match input_2 {\n"
-"    special_b(x) => { return x; }\n"
-"    _ => {}\n"
-"}\n"
-"# return 0u;\n"
-"# }\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:38
-msgid ""
-"This code could become tiresome if repeated many times.  However, no "
-"function can capture its functionality to make it possible to abstract the "
-"repetition away.  Rust's macro system, however, can eliminate the "
-"repetition. Macros are lightweight custom syntax extensions, themselves "
-"defined using the `macro_rules!` syntax extension. The following "
-"`early_return` macro captures the pattern in the above code:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:59
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# enum t { special_a(uint), special_b(uint) };\n"
-"# fn f() -> uint {\n"
-"# let input_1 = special_a(0);\n"
-"# let input_2 = special_a(0);\n"
-"macro_rules! early_return(\n"
-"    ($inp:expr $sp:ident) => ( // invoke it like `(input_5 special_e)`\n"
-"        match $inp {\n"
-"            $sp(x) => { return x; }\n"
-"            _ => {}\n"
-"        }\n"
-"    );\n"
-")\n"
-"// ...\n"
-"early_return!(input_1 special_a);\n"
-"// ...\n"
-"early_return!(input_2 special_b);\n"
-"# return 0;\n"
-"# }\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:65
-msgid ""
-"Macros are defined in pattern-matching style: in the above example, the text "
-"`($inp:expr $sp:ident)` that appears on the left-hand side of the `=>` is "
-"the *macro invocation syntax*, a pattern denoting how to write a call to the "
-"macro. The text on the right-hand side of the `=>`, beginning with `match "
-"$inp`, is the *macro transcription syntax*: what the macro expands to."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:67
-msgid "# Invocation syntax"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:71
-msgid ""
-"The macro invocation syntax specifies the syntax for the arguments to the "
-"macro. It appears on the left-hand side of the `=>` in a macro definition. "
-"It conforms to the following rules:"
-msgstr ""
-
-#. type: Bullet: '1. '
-#: doc/tutorial-macros.md:76
-msgid "It must be surrounded by parentheses."
-msgstr ""
-
-#. type: Bullet: '2. '
-#: doc/tutorial-macros.md:76
-msgid "`$` has special meaning (described below)."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:76
-#, no-wrap
-msgid ""
-"3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is\n"
-"forbidden.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:78
-msgid "Otherwise, the invocation syntax is free-form."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:83
-#, no-wrap
-msgid ""
-"To take as an argument a fragment of Rust code, write `$` followed by a name\n"
-" (for use on the right-hand side), followed by a `:`, followed by a *fragment\n"
-" specifier*. The fragment specifier denotes the sort of fragment to match. The\n"
-" most common fragment specifiers are:\n"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-macros.md:92
-msgid ""
-"`ident` (an identifier, referring to a variable or item. Examples: `f`, `x`, "
-"`foo`.)"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-macros.md:92
-msgid ""
-"`expr` (an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`; "
-"`f(42)`.)"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-macros.md:92
-msgid "`ty` (a type. Examples: `int`, `~[(char, ~str)]`, `&T`.)"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-macros.md:92
-msgid ""
-"`pat` (a pattern, usually appearing in a `match` or on the left-hand side of "
-"a declaration. Examples: `Some(t)`; `(17, 'a')`; `_`.)"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-macros.md:92
-msgid ""
-"`block` (a sequence of actions. Example: `{ log(error, \"hi\"); return 12; }"
-"`)"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:95
-msgid ""
-"The parser interprets any token that's not preceded by a `$` literally. "
-"Rust's usual rules of tokenization apply,"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:98
-msgid ""
-"So `($x:ident -> (($e:expr)))`, though excessively fancy, would designate a "
-"macro that could be invoked like: `my_macro!(i->(( 2+2 )))`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:100
-msgid "## Invocation location"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:105
-msgid ""
-"A macro invocation may take the place of (and therefore expand to)  an "
-"expression, an item, or a statement.  The Rust parser will parse the macro "
-"invocation as a \"placeholder\" for whichever of those three nonterminals is "
-"appropriate for the location."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:112
-msgid ""
-"At expansion time, the output of the macro will be parsed as whichever of "
-"the three nonterminals it stands in for. This means that a single macro "
-"might, for example, expand to an item or an expression, depending on its "
-"arguments (and cause a syntax error if it is called with the wrong argument "
-"for its location). Although this behavior sounds excessively dynamic, it is "
-"known to be useful under some circumstances."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:115
-msgid "# Transcription syntax"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:119
-msgid ""
-"The right-hand side of the `=>` follows the same rules as the left-hand "
-"side, except that a `$` need only be followed by the name of the syntactic "
-"fragment to transcribe into the macro expansion; its type need not be "
-"repeated."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:126
-msgid ""
-"The right-hand side must be enclosed by delimiters, which the transcriber "
-"ignores.  Therefore `() => ((1,2,3))` is a macro that expands to a tuple "
-"expression, `() => (let $x=$val)` is a macro that expands to a statement, "
-"and `() => (1,2,3)` is a macro that expands to a syntax error (since the "
-"transcriber interprets the parentheses on the right-hand-size as delimiters, "
-"and `1,2,3` is not a valid Rust expression on its own)."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:133
-msgid ""
-"Except for permissibility of `$name` (and `$(...)*`, discussed below), the "
-"right-hand side of a macro definition is ordinary Rust syntax. In "
-"particular, macro invocations (including invocations of the macro currently "
-"being defined)  are permitted in expression, statement, and item locations. "
-"However, nothing else about the code is examined or executed by the macro "
-"system; execution still has to wait until run-time."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:135
-msgid "## Interpolation location"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:139
-msgid ""
-"The interpolation `$argument_name` may appear in any location consistent "
-"with its fragment specifier (i.e., if it is specified as `ident`, it may be "
-"used anywhere an identifier is permitted)."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:141
-msgid "# Multiplicity"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:143
-msgid "## Invocation"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:150
-msgid ""
-"Going back to the motivating example, recall that `early_return` expanded "
-"into a `match` that would `return` if the `match`'s scrutinee matched the "
-"\"special case\" identifier provided as the second argument to "
-"`early_return`, and do nothing otherwise. Now suppose that we wanted to "
-"write a version of `early_return` that could handle a variable number of "
-"\"special\" cases."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:156
-msgid ""
-"The syntax `$(...)*` on the left-hand side of the `=>` in a macro definition "
-"accepts zero or more occurrences of its contents. It works much like the `*` "
-"operator in regular expressions. It also supports a separator token (a comma-"
-"separated list could be written `$(...),*`), and `+` instead of `*` to mean "
-"\"at least one\"."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:179
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# enum t { special_a(uint),special_b(uint),special_c(uint),special_d(uint)};\n"
-"# fn f() -> uint {\n"
-"# let input_1 = special_a(0);\n"
-"# let input_2 = special_a(0);\n"
-"macro_rules! early_return(\n"
-"    ($inp:expr, [ $($sp:ident)|+ ]) => (\n"
-"        match $inp {\n"
-"            $(\n"
-"                $sp(x) => { return x; }\n"
-"            )+\n"
-"            _ => {}\n"
-"        }\n"
-"    );\n"
-")\n"
-"// ...\n"
-"early_return!(input_1, [special_a|special_c|special_d]);\n"
-"// ...\n"
-"early_return!(input_2, [special_b]);\n"
-"# return 0;\n"
-"# }\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:181
-msgid "### Transcription"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:191
-msgid ""
-"As the above example demonstrates, `$(...)*` is also valid on the right-hand "
-"side of a macro definition. The behavior of `*` in transcription, especially "
-"in cases where multiple `*`s are nested, and multiple different names are "
-"involved, can seem somewhat magical and intuitive at first. The system that "
-"interprets them is called \"Macro By Example\". The two rules to keep in "
-"mind are (1) the behavior of `$(...)*` is to walk 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 repeated, as appropriate."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:193
-msgid "## Parsing limitations"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:197
-msgid ""
-"For technical reasons, there are two limitations to the treatment of syntax "
-"fragments by the macro parser:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:210
-#, no-wrap
-msgid ""
-"1. The parser will always parse as much as possible of a Rust syntactic\n"
-"fragment. For example, if the comma were omitted from the syntax of\n"
-"`early_return!` above, `input_1 [` would've been interpreted as the beginning\n"
-"of an array index. In fact, invoking the macro would have been impossible.\n"
-"2. The parser must have eliminated all ambiguity by the time it reaches a\n"
-"`$name:fragment_specifier` declaration. This limitation can result in parse\n"
-"errors when declarations occur at the beginning of, or immediately after,\n"
-"a `$(...)*`. For example, the grammar `$($t:ty)* $e:expr` will always fail to\n"
-"parse because the parser would be forced to choose between parsing `t` and\n"
-"parsing `e`. Changing the invocation syntax to require a distinctive token in\n"
-"front can solve the problem. In the above example, `$(T $t:ty)* E $e:exp`\n"
-"solves the problem.\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:212
-msgid "# Macro argument pattern matching"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:214
-msgid "Now consider code like the following:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:216
-msgid "## Motivation"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:236
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# enum t1 { good_1(t2, uint), bad_1 };\n"
-"# pub struct t2 { body: t3 }\n"
-"# enum t3 { good_2(uint), bad_2};\n"
-"# fn f(x: t1) -> uint {\n"
-"match x {\n"
-"    good_1(g1, val) => {\n"
-"        match g1.body {\n"
-"            good_2(result) => {\n"
-"                // complicated stuff goes here\n"
-"                return result + val;\n"
-"            },\n"
-"            _ => fail!(\"Didn't get good_2\")\n"
-"        }\n"
-"    }\n"
-"    _ => return 0 // default value\n"
-"}\n"
-"# }\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:241
-msgid ""
-"All the complicated stuff is deeply indented, and the error-handling code is "
-"separated from matches that fail. We'd like to write a macro that performs a "
-"match, but with a syntax that suits the problem better. The following macro "
-"can solve the problem:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:263
-#, no-wrap
-msgid ""
-"~~~~\n"
-"macro_rules! biased_match (\n"
-"    // special case: `let (x) = ...` is illegal, so use `let x = ...` instead\n"
-"    ( ($e:expr) ~ ($p:pat) else $err:stmt ;\n"
-"      binds $bind_res:ident\n"
-"    ) => (\n"
-"        let $bind_res = match $e {\n"
-"            $p => ( $bind_res ),\n"
-"            _ => { $err }\n"
-"        };\n"
-"    );\n"
-"    // more than one name; use a tuple\n"
-"    ( ($e:expr) ~ ($p:pat) else $err:stmt ;\n"
-"      binds $( $bind_res:ident ),*\n"
-"    ) => (\n"
-"        let ( $( $bind_res ),* ) = match $e {\n"
-"            $p => ( $( $bind_res ),* ),\n"
-"            _ => { $err }\n"
-"        };\n"
-"    )\n"
-")\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:277
-#, no-wrap
-msgid ""
-"# enum t1 { good_1(t2, uint), bad_1 };\n"
-"# pub struct t2 { body: t3 }\n"
-"# enum t3 { good_2(uint), bad_2};\n"
-"# fn f(x: t1) -> uint {\n"
-"biased_match!((x)       ~ (good_1(g1, val)) else { return 0 };\n"
-"              binds g1, val )\n"
-"biased_match!((g1.body) ~ (good_2(result) )\n"
-"                  else { fail!(\"Didn't get good_2\") };\n"
-"              binds result )\n"
-"// complicated stuff goes here\n"
-"return result + val;\n"
-"# }\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:288
-#, no-wrap
-msgid ""
-"This solves the indentation problem. But if we have a lot of chained matches\n"
-"like this, we might prefer to write a single macro invocation. The input\n"
-"pattern we want is clear:\n"
-"~~~~\n"
-"# macro_rules! b(\n"
-"    ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*\n"
-"      binds $( $bind_res:ident ),*\n"
-"    )\n"
-"# => (0))\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:291
-msgid ""
-"However, it's not possible to directly expand to nested match statements. "
-"But there is a solution."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:293
-msgid "## The recursive approach to macro writing"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:297
-msgid ""
-"A macro may accept multiple different input grammars. The first one to "
-"successfully match the actual argument to a macro invocation is the one that "
-"\"wins\"."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:301
-msgid ""
-"In the case of the example above, we want to write a recursive macro to "
-"process the semicolon-terminated lines, one-by-one. So, we want the "
-"following input patterns:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:308
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# macro_rules! b(\n"
-"    ( binds $( $bind_res:ident ),* )\n"
-"# => (0))\n"
-"~~~~\n"
-"...and:\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:317
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# macro_rules! b(\n"
-"    (    ($e     :expr) ~ ($p     :pat) else $err     :stmt ;\n"
-"      $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*\n"
-"      binds  $( $bind_res:ident ),*\n"
-"    )\n"
-"# => (0))\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:321
-msgid ""
-"The resulting macro looks like this. Note that the separation into "
-"`biased_match!` and `biased_match_rec!` occurs only because we have an outer "
-"piece of syntax (the `let`) which we only want to transcribe once."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:342
-#, no-wrap
-msgid ""
-"macro_rules! biased_match_rec (\n"
-"    // Handle the first layer\n"
-"    (   ($e     :expr) ~ ($p     :pat) else $err     :stmt ;\n"
-"     $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*\n"
-"     binds $( $bind_res:ident ),*\n"
-"    ) => (\n"
-"        match $e {\n"
-"            $p => {\n"
-"                // Recursively handle the next layer\n"
-"                biased_match_rec!($( ($e_rest) ~ ($p_rest) else $err_rest ; )*\n"
-"                                  binds $( $bind_res ),*\n"
-"                )\n"
-"            }\n"
-"            _ => { $err }\n"
-"        }\n"
-"    );\n"
-"    ( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )\n"
-")\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:364
-#, no-wrap
-msgid ""
-"// Wrap the whole thing in a `let`.\n"
-"macro_rules! biased_match (\n"
-"    // special case: `let (x) = ...` is illegal, so use `let x = ...` instead\n"
-"    ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*\n"
-"      binds $bind_res:ident\n"
-"    ) => (\n"
-"        let ( $( $bind_res ),* ) = biased_match_rec!(\n"
-"            $( ($e) ~ ($p) else $err ; )*\n"
-"            binds $bind_res\n"
-"        );\n"
-"    );\n"
-"    // more than one name: use a tuple\n"
-"    ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*\n"
-"      binds  $( $bind_res:ident ),*\n"
-"    ) => (\n"
-"        let ( $( $bind_res ),* ) = biased_match_rec!(\n"
-"            $( ($e) ~ ($p) else $err ; )*\n"
-"            binds $( $bind_res ),*\n"
-"        );\n"
-"    )\n"
-")\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:378
-#, no-wrap
-msgid ""
-"# enum t1 { good_1(t2, uint), bad_1 };\n"
-"# pub struct t2 { body: t3 }\n"
-"# enum t3 { good_2(uint), bad_2};\n"
-"# fn f(x: t1) -> uint {\n"
-"biased_match!(\n"
-"    (x)       ~ (good_1(g1, val)) else { return 0 };\n"
-"    (g1.body) ~ (good_2(result) ) else { fail!(\"Didn't get good_2\") };\n"
-"    binds val, result )\n"
-"// complicated stuff goes here\n"
-"return result + val;\n"
-"# }\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:382
-msgid ""
-"This technique applies to many cases where transcribing a result all at once "
-"is not possible.  The resulting code resembles ordinary functional "
-"programming in some respects, but has some important differences from "
-"functional programming."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:390
-msgid ""
-"The first difference is important, but also easy to forget: the "
-"transcription (right-hand) side of a `macro_rules!` rule is literal syntax, "
-"which can only be executed at run-time. If a piece of transcription syntax "
-"does not itself appear inside another macro invocation, it will become part "
-"of the final program. If it is inside a macro invocation (for example, the "
-"recursive invocation of `biased_match_rec!`), it does have the opportunity "
-"to affect transcription, but only through the process of attempted pattern "
-"matching."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:398
-msgid ""
-"The second, related, difference is that the evaluation order of macros feels "
-"\"backwards\" compared to ordinary programming. Given an invocation `m1!(m2!"
-"())`, the expander first expands `m1!`, giving it as input the literal "
-"syntax `m2!()`. If it transcribes its argument unchanged into an appropriate "
-"position (in particular, not as an argument to yet another macro "
-"invocation), the expander will then proceed to evaluate `m2!()` (along with "
-"any other macro invocations `m1!(m2!())` produced)."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:400
-msgid "# A final note"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-macros.md:407
-msgid ""
-"Macros, as currently implemented, are not for the faint of heart. Even "
-"ordinary syntax errors can be more difficult to debug when they occur inside "
-"a macro, and errors caused by parse problems in generated code can be very "
-"tricky. Invoking the `log_syntax!` macro can help elucidate intermediate "
-"states, invoking `trace_macros!(true)` will automatically print those "
-"intermediate states out, and passing the flag `--pretty expanded` as a "
-"command-line argument to the compiler will show the result of expansion."
-msgstr ""
diff --git a/doc/po/ja/tutorial-tasks.md.po b/doc/po/ja/tutorial-tasks.md.po
deleted file mode 100644 (file)
index 2276d00..0000000
+++ /dev/null
@@ -1,1070 +0,0 @@
-# Japanese translations for Rust package
-# Copyright (C) 2013 The Rust Project Developers
-# This file is distributed under the same license as the Rust package.
-# Automatically generated, 2013.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Rust 0.8\n"
-"POT-Creation-Date: 2013-08-08 22:27+0900\n"
-"PO-Revision-Date: 2013-07-28 20:32+0900\n"
-"Last-Translator: Automatically generated\n"
-"Language-Team: none\n"
-"Language: ja\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#. type: Plain text
-#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
-#: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
-#: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
-msgid "# Introduction"
-msgstr "# イントロダクション"
-
-#. type: Plain text
-#: doc/rust.md:1952 doc/tutorial-tasks.md:648
-msgid "# } ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:2
-msgid "% Rust Tasks and Communication Tutorial"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:10
-msgid ""
-"Rust provides safe concurrency through a combination of lightweight, memory-"
-"isolated tasks and message passing.  This tutorial will describe the "
-"concurrency model in Rust, how it relates to the Rust type system, and "
-"introduce the fundamental library abstractions for constructing concurrent "
-"programs."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:19
-msgid ""
-"Rust tasks are not the same as traditional threads: rather, they are "
-"considered _green threads_, lightweight units of execution that the Rust "
-"runtime schedules cooperatively onto a small number of operating system "
-"threads.  On a multi-core system Rust tasks will be scheduled in parallel by "
-"default.  Because tasks are significantly cheaper to create than traditional "
-"threads, Rust can create hundreds of thousands of concurrent tasks on a "
-"typical 32-bit system.  In general, all Rust code executes inside a task, "
-"including the `main` function."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:26
-msgid ""
-"In order to make efficient use of memory Rust tasks have dynamically sized "
-"stacks.  A task begins its life with a small amount of stack space "
-"(currently in the low thousands of bytes, depending on platform), and "
-"acquires more stack as needed.  Unlike in languages such as C, a Rust task "
-"cannot accidentally write to memory beyond the end of the stack, causing "
-"crashes or worse."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:32
-msgid ""
-"Tasks provide failure isolation and recovery. When a fatal error occurs in "
-"Rust code as a result of an explicit call to `fail!()`, an assertion "
-"failure, or another invalid operation, the runtime system destroys the "
-"entire task. Unlike in languages such as Java and C++, there is no way to "
-"`catch` an exception. Instead, tasks may monitor each other for failure."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:37
-msgid ""
-"Tasks use Rust's type system to provide strong memory safety guarantees. In "
-"particular, the type system guarantees that tasks cannot share mutable state "
-"with each other. Tasks communicate with each other by transferring _owned_ "
-"data through the global _exchange heap_."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:39
-msgid "## A note about the libraries"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:44
-msgid ""
-"While Rust's type system provides the building blocks needed for safe and "
-"efficient tasks, all of the task functionality itself is implemented in the "
-"standard and extra libraries, which are still under development and do not "
-"always present a consistent or complete interface."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:47
-msgid ""
-"For your reference, these are the standard modules involved in Rust "
-"concurrency at this writing:"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-tasks.md:56
-msgid "[`std::task`] - All code relating to tasks and task scheduling,"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-tasks.md:56
-msgid "[`std::comm`] - The message passing interface,"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-tasks.md:56
-msgid "[`std::pipes`] - The underlying messaging infrastructure,"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-tasks.md:56
-msgid "[`extra::comm`] - Additional messaging types based on `std::pipes`,"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-tasks.md:56
-msgid "[`extra::sync`] - More exotic synchronization tools, including locks,"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-tasks.md:56
-msgid ""
-"[`extra::arc`] - The Arc (atomically reference counted) type, for safely "
-"sharing immutable data,"
-msgstr ""
-
-#. type: Bullet: '* '
-#: doc/tutorial-tasks.md:56
-msgid ""
-"[`extra::future`] - A type representing values that may be computed "
-"concurrently and retrieved at a later time."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:64
-msgid ""
-"[`std::task`]: std/task.html [`std::comm`]: std/comm.html [`std::pipes`]: "
-"std/pipes.html [`extra::comm`]: extra/comm.html [`extra::sync`]: extra/sync."
-"html [`extra::arc`]: extra/arc.html [`extra::future`]: extra/future.html"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:66
-msgid "# Basics"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:72
-msgid ""
-"The programming interface for creating and managing tasks lives in the "
-"`task` module of the `std` library, and is thus available to all Rust code "
-"by default. At its simplest, creating a task is a matter of calling the "
-"`spawn` function with a closure argument. `spawn` executes the closure in "
-"the new task."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:76
-msgid "~~~~ # use std::io::println; # use std::task::spawn;"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:80
-msgid ""
-"// Print something profound in a different task using a named function fn "
-"print_message() { println(\"I am running in a different task!\"); } "
-"spawn(print_message);"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:83
-msgid ""
-"// Print something more profound in a different task using a lambda "
-"expression spawn( || println(\"I am also running in a different task!\") );"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:89
-#, no-wrap
-msgid ""
-"// The canonical way to spawn is using `do` notation\n"
-"do spawn {\n"
-"    println(\"I too am running in a different task!\");\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:95
-msgid ""
-"In Rust, there is nothing special about creating tasks: a task is not a "
-"concept that appears in the language semantics. Instead, Rust's type system "
-"provides all the tools necessary to implement safe concurrency: "
-"particularly, _owned types_. The language leaves the implementation details "
-"to the standard library."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:102
-msgid ""
-"The `spawn` function has a very simple type signature: `fn spawn(f: proc())`. "
-"Because it accepts only owned closures, and owned closures contain only "
-"owned data, `spawn` can safely move the entire closure and all its "
-"associated state into an entirely different task for execution. Like any "
-"closure, the function passed to `spawn` may capture an environment that it "
-"carries across tasks."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:109
-msgid ""
-"~~~ # use std::io::println; # use std::task::spawn; # fn "
-"generate_task_number() -> int { 0 } // Generate some state locally let "
-"child_task_number = generate_task_number();"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:115
-#, no-wrap
-msgid ""
-"do spawn {\n"
-"   // Capture it in the remote task\n"
-"   println(fmt!(\"I am child number %d\", child_task_number));\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:119
-msgid ""
-"By default, the scheduler multiplexes tasks across the available cores, "
-"running in parallel. Thus, on a multicore machine, running the following "
-"code should interleave the output in vaguely random order."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:123
-msgid "~~~ # use std::io::print; # use std::task::spawn;"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:130
-#, no-wrap
-msgid ""
-"for child_task_number in range(0, 20) {\n"
-"    do spawn {\n"
-"       print(fmt!(\"I am child number %d\\n\", child_task_number));\n"
-"    }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:132
-msgid "## Communication"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:137
-msgid ""
-"Now that we have spawned a new task, it would be nice if we could "
-"communicate with it. Recall that Rust does not have shared mutable state, so "
-"one task may not manipulate variables owned by another task.  Instead we use "
-"*pipes*."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:142
-msgid ""
-"A pipe is simply a pair of endpoints: one for sending messages and another "
-"for receiving messages. Pipes are low-level communication building-blocks "
-"and so come in a variety of forms, each one appropriate for a different use "
-"case. In what follows, we cover the most commonly used varieties."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:148
-msgid ""
-"The simplest way to create a pipe is to use the `pipes::stream` function to "
-"create a `(Port, Chan)` pair. In Rust parlance, a *channel* is a sending "
-"endpoint of a pipe, and a *port* is the receiving endpoint. Consider the "
-"following example of calculating two results concurrently:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:152
-msgid "~~~~ # use std::task::spawn; # use std::comm::{stream, Port, Chan};"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:154
-msgid "let (port, chan): (Port<int>, Chan<int>) = stream();"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:159
-#, no-wrap
-msgid ""
-"do spawn || {\n"
-"    let result = some_expensive_computation();\n"
-"    chan.send(result);\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:165
-msgid ""
-"some_other_expensive_computation(); let result = port.recv(); # fn "
-"some_expensive_computation() -> int { 42 } # fn "
-"some_other_expensive_computation() {} ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:170
-msgid ""
-"Let's examine this example in detail. First, the `let` statement creates a "
-"stream for sending and receiving integers (the left-hand side of the `let`, "
-"`(chan, port)`, is an example of a *destructuring let*: the pattern "
-"separates a tuple into its component parts)."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:175
-msgid ""
-"~~~~ # use std::comm::{stream, Chan, Port}; let (port, chan): (Port<int>, "
-"Chan<int>) = stream(); ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:179
-msgid ""
-"The child task will use the channel to send data to the parent task, which "
-"will wait to receive the data on the port. The next statement spawns the "
-"child task."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:190
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# use std::task::spawn;\n"
-"# use std::comm::stream;\n"
-"# fn some_expensive_computation() -> int { 42 }\n"
-"# let (port, chan) = stream();\n"
-"do spawn || {\n"
-"    let result = some_expensive_computation();\n"
-"    chan.send(result);\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:196
-msgid ""
-"Notice that the creation of the task closure transfers `chan` to the child "
-"task implicitly: the closure captures `chan` in its environment. Both `Chan` "
-"and `Port` are sendable types and may be captured into tasks or otherwise "
-"transferred between them. In the example, the child task runs an expensive "
-"computation, then sends the result over the captured channel."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:200
-msgid ""
-"Finally, the parent continues with some other expensive computation, then "
-"waits for the child's result to arrive on the port:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:209
-msgid ""
-"~~~~ # use std::comm::{stream}; # fn some_other_expensive_computation() {} # "
-"let (port, chan) = stream::<int>(); # chan.send(0); "
-"some_other_expensive_computation(); let result = port.recv(); ~~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:215
-msgid ""
-"The `Port` and `Chan` pair created by `stream` enables efficient "
-"communication between a single sender and a single receiver, but multiple "
-"senders cannot use a single `Chan`, and multiple receivers cannot use a "
-"single `Port`.  What if our example needed to compute multiple results "
-"across a number of tasks? The following program is ill-typed:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:221
-msgid ""
-"~~~ {.xfail-test} # use std::task::{spawn}; # use std::comm::{stream, Port, "
-"Chan}; # fn some_expensive_computation() -> int { 42 } let (port, chan) = "
-"stream();"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:225
-#, no-wrap
-msgid ""
-"do spawn {\n"
-"    chan.send(some_expensive_computation());\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:232
-#, no-wrap
-msgid ""
-"// ERROR! The previous spawn statement already owns the channel,\n"
-"// so the compiler will not allow it to be captured again\n"
-"do spawn {\n"
-"    chan.send(some_expensive_computation());\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:235
-msgid ""
-"Instead we can use a `SharedChan`, a type that allows a single `Chan` to be "
-"shared by multiple senders."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:239
-msgid "~~~ # use std::task::spawn; # use std::comm::{stream, SharedChan};"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:242
-msgid "let (port, chan) = stream(); let chan = SharedChan::new(chan);"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:250
-#, no-wrap
-msgid ""
-"for init_val in range(0u, 3) {\n"
-"    // Create a new channel handle to distribute to the child task\n"
-"    let child_chan = chan.clone();\n"
-"    do spawn {\n"
-"        child_chan.send(some_expensive_computation(init_val));\n"
-"    }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:254
-msgid ""
-"let result = port.recv() + port.recv() + port.recv(); # fn "
-"some_expensive_computation(_i: uint) -> int { 42 } ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:263
-msgid ""
-"Here we transfer ownership of the channel into a new `SharedChan` value.  "
-"Like `Chan`, `SharedChan` is a non-copyable, owned type (sometimes also "
-"referred to as an *affine* or *linear* type). Unlike with `Chan`, though, "
-"the programmer may duplicate a `SharedChan`, with the `clone()` method.  A "
-"cloned `SharedChan` produces a new handle to the same channel, allowing "
-"multiple tasks to send data to a single port.  Between `spawn`, `stream` and "
-"`SharedChan`, we have enough tools to implement many useful concurrency "
-"patterns."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:268
-msgid ""
-"Note that the above `SharedChan` example is somewhat contrived since you "
-"could also simply use three `stream` pairs, but it serves to illustrate the "
-"point. For reference, written with multiple streams, it might look like the "
-"example below."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:273
-msgid "~~~ # use std::task::spawn; # use std::comm::stream; # use std::vec;"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:282
-#, no-wrap
-msgid ""
-"// Create a vector of ports, one for each child task\n"
-"let ports = do vec::from_fn(3) |init_val| {\n"
-"    let (port, chan) = stream();\n"
-"    do spawn {\n"
-"        chan.send(some_expensive_computation(init_val));\n"
-"    }\n"
-"    port\n"
-"};\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:287
-msgid ""
-"// Wait on each port, accumulating the results let result = ports.iter()."
-"fold(0, |accum, port| accum + port.recv() ); # fn "
-"some_expensive_computation(_i: uint) -> int { 42 } ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:291
-msgid ""
-"## Backgrounding computations: Futures With `extra::future`, rust has a "
-"mechanism for requesting a computation and getting the result later."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:299
-#, no-wrap
-msgid ""
-"The basic example below illustrates this.\n"
-"~~~\n"
-"# fn make_a_sandwich() {};\n"
-"fn fib(n: u64) -> u64 {\n"
-"    // lengthy computation returning an uint\n"
-"    12586269025\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:304
-msgid ""
-"let mut delayed_fib = extra::future::spawn (|| fib(50) ); make_a_sandwich(); "
-"println(fmt!(\"fib(50) = %?\", delayed_fib.get()))  ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:310
-msgid ""
-"The call to `future::spawn` returns immediately a `future` object regardless "
-"of how long it takes to run `fib(50)`. You can then make yourself a sandwich "
-"while the computation of `fib` is running. The result of the execution of "
-"the method is obtained by calling `get` on the future.  This call will block "
-"until the value is available (*i.e.* the computation is complete). Note that "
-"the future needs to be mutable so that it can save the result for next time "
-"`get` is called."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:322
-#, no-wrap
-msgid ""
-"Here is another example showing how futures allow you to background computations. The workload will\n"
-"be distributed on the available cores.\n"
-"~~~\n"
-"# use std::vec;\n"
-"fn partial_sum(start: uint) -> f64 {\n"
-"    let mut local_sum = 0f64;\n"
-"    for num in range(start*100000, (start+1)*100000) {\n"
-"        local_sum += (num as f64 + 1.0).pow(&-2.0);\n"
-"    }\n"
-"    local_sum\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:325
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"    let mut futures = vec::from_fn(1000, |ind| do extra::future::spawn { partial_sum(ind) });\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:333
-#, no-wrap
-msgid ""
-"    let mut final_res = 0f64;\n"
-"    for ft in futures.mut_iter()  {\n"
-"        final_res += ft.get();\n"
-"    }\n"
-"    println(fmt!(\"π^2/6 is not far from : %?\", final_res));\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:335
-msgid "## Sharing immutable data without copy: Arc"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:340
-msgid ""
-"To share immutable data between tasks, a first approach would be to only use "
-"pipes as we have seen previously. A copy of the data to share would then be "
-"made for each task. In some cases, this would add up to a significant amount "
-"of wasted memory and would require copying the same data more than necessary."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:344
-msgid ""
-"To tackle this issue, one can use an Atomically Reference Counted wrapper "
-"(`Arc`) as implemented in the `extra` library of Rust. With an Arc, the data "
-"will no longer be copied for each task. The Arc acts as a reference to the "
-"shared data and only this reference is shared and cloned."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:351
-msgid ""
-"Here is a small example showing how to use Arcs. We wish to run concurrently "
-"several computations on a single large vector of floats. Each task needs the "
-"full vector to perform its duty.  ~~~ # use std::vec; # use std::rand; use "
-"extra::arc::Arc;"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:355
-#, no-wrap
-msgid ""
-"fn pnorm(nums: &~[float], p: uint) -> float {\n"
-"    nums.iter().fold(0.0, |a,b| a+(*b).pow(&(p as float)) ).pow(&(1f / (p as float)))\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:359
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"    let numbers = vec::from_fn(1000000, |_| rand::random::<float>());\n"
-"    println(fmt!(\"Inf-norm = %?\",  *numbers.iter().max().unwrap()));\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:361
-#, no-wrap
-msgid "    let numbers_arc = Arc::new(numbers);\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:365
-#, no-wrap
-msgid ""
-"    for num in range(1u, 10) {\n"
-"        let (port, chan)  = stream();\n"
-"        chan.send(numbers_arc.clone());\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:374
-#, no-wrap
-msgid ""
-"        do spawn {\n"
-"            let local_arc : Arc<~[float]> = port.recv();\n"
-"            let task_numbers = local_arc.get();\n"
-"            println(fmt!(\"%u-norm = %?\", num, pnorm(task_numbers, num)));\n"
-"        }\n"
-"    }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:396
-msgid ""
-"The function `pnorm` performs a simple computation on the vector (it "
-"computes the sum of its items at the power given as argument and takes the "
-"inverse power of this value). The Arc on the vector is created by the line "
-"~~~ # use extra::arc::Arc; # use std::vec; # use std::rand; # let numbers = "
-"vec::from_fn(1000000, |_| rand::random::<float>()); let numbers_arc=Arc::"
-"new(numbers); ~~~ and a clone of it is sent to each task ~~~ # use extra::"
-"arc::Arc; # use std::vec; # use std::rand; # let numbers=vec::"
-"from_fn(1000000, |_| rand::random::<float>()); # let numbers_arc = Arc::"
-"new(numbers); # let (port, chan)  = stream(); chan.send(numbers_arc."
-"clone()); ~~~ copying only the wrapper and not its contents."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:410
-msgid ""
-"Each task recovers the underlying data by ~~~ # use extra::arc::Arc; # use "
-"std::vec; # use std::rand; # let numbers=vec::from_fn(1000000, |_| rand::"
-"random::<float>()); # let numbers_arc=Arc::new(numbers); # let (port, chan)  "
-"= stream(); # chan.send(numbers_arc.clone()); # let local_arc : "
-"Arc<~[float]> = port.recv(); let task_numbers = local_arc.get(); ~~~ and can "
-"use it as if it were local."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:412
-msgid ""
-"The `arc` module also implements Arcs around mutable data that are not "
-"covered here."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:414
-msgid "# Handling task failure"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:423
-msgid ""
-"Rust has a built-in mechanism for raising exceptions. The `fail!()` macro "
-"(which can also be written with an error string as an argument: `fail!"
-"( ~reason)`) and the `assert!` construct (which effectively calls `fail!()` "
-"if a boolean expression is false) are both ways to raise exceptions. When a "
-"task raises an exception the task unwinds its stack---running destructors "
-"and freeing memory along the way---and then exits. Unlike exceptions in C++, "
-"exceptions in Rust are unrecoverable within a single task: once a task "
-"fails, there is no way to \"catch\" the exception."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:426
-msgid ""
-"All tasks are, by default, _linked_ to each other. That means that the fates "
-"of all tasks are intertwined: if one fails, so do all the others."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:434
-msgid ""
-"~~~{.xfail-test .linked-failure} # use std::task::spawn; # use std::task; # "
-"fn do_some_work() { loop { task::yield() } } # do task::try { // Create a "
-"child task that fails do spawn { fail!() }"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:439
-msgid ""
-"// This will also fail because the task we spawned failed do_some_work(); "
-"# }; ~~~"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:449
-msgid ""
-"While it isn't possible for a task to recover from failure, tasks may notify "
-"each other of failure. The simplest way of handling task failure is with the "
-"`try` function, which is similar to `spawn`, but immediately blocks waiting "
-"for the child task to finish. `try` returns a value of type `Result<int, "
-"()>`. `Result` is an `enum` type with two variants: `Ok` and `Err`. In this "
-"case, because the type arguments to `Result` are `int` and `()`, callers can "
-"pattern-match on a result to check whether it's an `Ok` result with an `int` "
-"field (representing a successful result) or an `Err` result (representing "
-"termination with an error)."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:463
-#, no-wrap
-msgid ""
-"~~~{.xfail-test .linked-failure}\n"
-"# use std::task;\n"
-"# fn some_condition() -> bool { false }\n"
-"# fn calculate_result() -> int { 0 }\n"
-"let result: Result<int, ()> = do task::try {\n"
-"    if some_condition() {\n"
-"        calculate_result()\n"
-"    } else {\n"
-"        fail!(\"oops!\");\n"
-"    }\n"
-"};\n"
-"assert!(result.is_err());\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:469
-msgid ""
-"Unlike `spawn`, the function spawned using `try` may return a value, which "
-"`try` will dutifully propagate back to the caller in a [`Result`] enum. If "
-"the child task terminates successfully, `try` will return an `Ok` result; if "
-"the child task fails, `try` will return an `Error` result."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:471
-msgid "[`Result`]: std/result.html"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:476
-msgid ""
-"> ***Note:*** A failed task does not currently produce a useful error > "
-"value (`try` always returns `Err(())`). In the > future, it may be possible "
-"for tasks to intercept the value passed to > `fail!()`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:479
-msgid ""
-"TODO: Need discussion of `future_result` in order to make failure modes "
-"useful."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:487
-msgid ""
-"But not all failures are created equal. In some cases you might need to "
-"abort the entire program (perhaps you're writing an assert which, if it "
-"trips, indicates an unrecoverable logic error); in other cases you might "
-"want to contain the failure at a certain boundary (perhaps a small piece of "
-"input from the outside world, which you happen to be processing in parallel, "
-"is malformed and its processing task can't proceed). Hence, you will need "
-"different _linked failure modes_."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:489
-msgid "## Failure modes"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:492
-msgid ""
-"By default, task failure is _bidirectionally linked_, which means that if "
-"either task fails, it kills the other one."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:507
-#, no-wrap
-msgid ""
-"~~~{.xfail-test .linked-failure}\n"
-"# use std::task;\n"
-"# use std::comm::oneshot;\n"
-"# fn sleep_forever() { loop { let (p, c) = oneshot::<()>(); p.recv(); } }\n"
-"# do task::try {\n"
-"do spawn {\n"
-"    do spawn {\n"
-"        fail!();  // All three tasks will fail.\n"
-"    }\n"
-"    sleep_forever();  // Will get woken up by force, then fail\n"
-"}\n"
-"sleep_forever();  // Will get woken up by force, then fail\n"
-"# };\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:514
-msgid ""
-"If you want parent tasks to be able to kill their children, but do not want "
-"a parent to fail automatically if one of its child task fails, you can call "
-"`task::spawn_supervised` for _unidirectionally linked_ failure. The function "
-"`task::try`, which we saw previously, uses `spawn_supervised` internally, "
-"with additional logic to wait for the child task to finish before returning. "
-"Hence:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:536
-#, no-wrap
-msgid ""
-"~~~{.xfail-test .linked-failure}\n"
-"# use std::comm::{stream, Chan, Port};\n"
-"# use std::comm::oneshot;\n"
-"# use std::task::{spawn, try};\n"
-"# use std::task;\n"
-"# fn sleep_forever() { loop { let (p, c) = oneshot::<()>(); p.recv(); } }\n"
-"# do task::try {\n"
-"let (receiver, sender): (Port<int>, Chan<int>) = stream();\n"
-"do spawn {  // Bidirectionally linked\n"
-"    // Wait for the supervised child task to exist.\n"
-"    let message = receiver.recv();\n"
-"    // Kill both it and the parent task.\n"
-"    assert!(message != 42);\n"
-"}\n"
-"do try {  // Unidirectionally linked\n"
-"    sender.send(42);\n"
-"    sleep_forever();  // Will get woken up by force\n"
-"}\n"
-"// Flow never reaches here -- parent task was killed too.\n"
-"# };\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:542
-msgid ""
-"Supervised failure is useful in any situation where one task manages "
-"multiple fallible child tasks, and the parent task can recover if any child "
-"fails. On the other hand, if the _parent_ (supervisor) fails, then there is "
-"nothing the children can do to recover, so they should also fail."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:545
-msgid ""
-"Supervised task failure propagates across multiple generations even if an "
-"intermediate generation has already exited:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:562
-#, no-wrap
-msgid ""
-"~~~{.xfail-test .linked-failure}\n"
-"# use std::task;\n"
-"# use std::comm::oneshot;\n"
-"# fn sleep_forever() { loop { let (p, c) = oneshot::<()>(); p.recv(); } }\n"
-"# fn wait_for_a_while() { for _ in range(0, 1000u) { task::yield() } }\n"
-"# do task::try::<int> {\n"
-"do task::spawn_supervised {\n"
-"    do task::spawn_supervised {\n"
-"        sleep_forever();  // Will get woken up by force, then fail\n"
-"    }\n"
-"    // Intermediate task immediately exits\n"
-"}\n"
-"wait_for_a_while();\n"
-"fail!();  // Will kill grandchild even if child has already exited\n"
-"# };\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:565
-msgid ""
-"Finally, tasks can be configured to not propagate failure to each other at "
-"all, using `task::spawn_unlinked` for _isolated failure_."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:581
-#, no-wrap
-msgid ""
-"~~~{.xfail-test .linked-failure}\n"
-"# use std::task;\n"
-"# fn random() -> uint { 100 }\n"
-"# fn sleep_for(i: uint) { for _ in range(0, i) { task::yield() } }\n"
-"# do task::try::<()> {\n"
-"let (time1, time2) = (random(), random());\n"
-"do task::spawn_unlinked {\n"
-"    sleep_for(time2);  // Won't get forced awake\n"
-"    fail!();\n"
-"}\n"
-"sleep_for(time1);  // Won't get forced awake\n"
-"fail!();\n"
-"// It will take MAX(time1,time2) for the program to finish.\n"
-"# };\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:583
-msgid "## Creating a task with a bi-directional communication path"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:588
-msgid ""
-"A very common thing to do is to spawn a child task where the parent and "
-"child both need to exchange messages with each other. The function `extra::"
-"comm::DuplexStream()` supports this pattern.  We'll look briefly at how to "
-"use it."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:593
-msgid ""
-"To see how `DuplexStream()` works, we will create a child task that "
-"repeatedly receives a `uint` message, converts it to a string, and sends the "
-"string in response.  The child terminates when it receives `0`.  Here is the "
-"function that implements the child task:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:606
-#, no-wrap
-msgid ""
-"~~~{.xfail-test .linked-failure}\n"
-"# use extra::comm::DuplexStream;\n"
-"# use std::uint;\n"
-"fn stringifier(channel: &DuplexStream<~str, uint>) {\n"
-"    let mut value: uint;\n"
-"    loop {\n"
-"        value = channel.recv();\n"
-"        channel.send(uint::to_str(value));\n"
-"        if value == 0 { break; }\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:614
-msgid ""
-"The implementation of `DuplexStream` supports both sending and receiving. "
-"The `stringifier` function takes a `DuplexStream` that can send strings (the "
-"first type parameter) and receive `uint` messages (the second type "
-"parameter). The body itself simply loops, reading from the channel and then "
-"sending its response back.  The actual response itself is simply the "
-"stringified version of the received value, `uint::to_str(value)`."
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:616
-msgid "Here is the code for the parent task:"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:630
-#, no-wrap
-msgid ""
-"~~~{.xfail-test .linked-failure}\n"
-"# use std::task::spawn;\n"
-"# use std::uint;\n"
-"# use extra::comm::DuplexStream;\n"
-"# fn stringifier(channel: &DuplexStream<~str, uint>) {\n"
-"#     let mut value: uint;\n"
-"#     loop {\n"
-"#         value = channel.recv();\n"
-"#         channel.send(uint::to_str(value));\n"
-"#         if value == 0u { break; }\n"
-"#     }\n"
-"# }\n"
-"# fn main() {\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:632
-msgid "let (from_child, to_child) = DuplexStream();"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:636
-#, no-wrap
-msgid ""
-"do spawn {\n"
-"    stringifier(&to_child);\n"
-"};\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:639
-msgid "from_child.send(22); assert!(from_child.recv() == ~\"22\");"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:642
-msgid "from_child.send(23); from_child.send(0);"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:645
-msgid ""
-"assert!(from_child.recv() == ~\"23\"); assert!(from_child.recv() == ~\"0\");"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial-tasks.md:652
-msgid ""
-"The parent task first calls `DuplexStream` to create a pair of bidirectional "
-"endpoints. It then uses `task::spawn` to create the child task, which "
-"captures one end of the communication channel.  As a result, both parent and "
-"child can send and receive data to and from the other."
-msgstr ""
index 1d3fc494efac042d07c5ba2232d1c8ad2d1babfd..1c47dba9f04b4e3b4b8ec4431e93a08f905e5ca9 100644 (file)
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: Rust 0.8\n"
-"POT-Creation-Date: 2013-08-12 02:06+0900\n"
+"POT-Creation-Date: 2014-01-14 21:02+0900\n"
 "PO-Revision-Date: 2013-08-08 22:27+0900\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -17,47 +17,38 @@ msgstr ""
 "Plural-Forms: nplurals=1; plural=0;\n"
 
 #. type: Plain text
+#: doc/guide-conditions.md:4 doc/guide-ffi.md:4 doc/guide-lifetimes.md:4
+#: doc/guide-macros.md:4 doc/guide-rustpkg.md:4 doc/guide-tasks.md:4
 #: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
-#: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
-#: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
 msgid "# Introduction"
 msgstr "# イントロダクション"
 
 #. type: Plain text
-#: doc/rust.md:1277 doc/tutorial.md:2176
-msgid ""
-"In type-parameterized functions, methods of the supertrait may be called on "
-"values of subtrait-bound type parameters.  Refering to the previous example "
-"of `trait Circle : Shape`:"
-msgstr ""
-"型パラメータを持つ関数では、サブトレイトの境界型パラメータの値によりスーパー"
-"トレイトのメソッドを呼び出すことになります。前の例の `trait Circle : Shape` "
-"を参照してください。"
+#: doc/guide-ffi.md:168 doc/tutorial.md:875
+msgid "# Destructors"
+msgstr "# デストラクタ"
 
 #. type: Plain text
-#: doc/rust.md:1286 doc/tutorial.md:2185
-#, no-wrap
-msgid ""
-"~~~\n"
-"# trait Shape { fn area(&self) -> f64; }\n"
-"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
-"fn radius_times_area<T: Circle>(c: T) -> f64 {\n"
-"    // `c` is both a Circle and a Shape\n"
-"    c.radius() * c.area()\n"
-"}\n"
-"~~~\n"
+#: doc/guide-lifetimes.md:72 doc/tutorial.md:1394
+msgid "Now we can call `compute_distance()` in various ways:"
 msgstr ""
-"~~~\n"
-"# trait Shape { fn area(&self) -> f64; }\n"
-"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
-"fn radius_times_area<T: Circle>(c: T) -> f64 {\n"
-"    // `c` は Circle でもあり、Shape でもある\n"
-"    c.radius() * c.area()\n"
-"}\n"
-"~~~\n"
+"上記の `compute_distance()` 関数は、様々な方法で呼び出すことができます。"
+
+#. type: Plain text
+#: doc/guide-pointers.md:326 doc/tutorial.md:1345
+#, fuzzy
+msgid "# References"
+msgstr "# ポインタのデリファレンス"
+
+#. type: Plain text
+#: doc/guide-testing.md:127 doc/tutorial.md:776
+#, fuzzy
+#| msgid "## A minimal example"
+msgid "For example:"
+msgstr "## 最小限の例"
 
 #. type: Plain text
-#: doc/rust.md:1288 doc/tutorial.md:2187
+#: doc/rust.md:1388 doc/tutorial.md:2508
 msgid "Likewise, supertrait methods may also be called on trait objects."
 msgstr ""
 "同様に、スーパートレイトのメソッドは、トレイトオブジェクトについても呼び出す"
@@ -220,23 +211,36 @@ msgid "# Getting started"
 msgstr "# はじめに"
 
 #. type: Plain text
-#: doc/tutorial.md:63
+#: doc/tutorial.md:67
+#, fuzzy
+#| msgid ""
+#| "The Rust compiler currently must be built from a [tarball], unless you "
+#| "are on Windows, in which case using the [installer][win-exe] is "
+#| "recommended."
 msgid ""
-"The Rust compiler currently must be built from a [tarball], unless you are "
-"on Windows, in which case using the [installer][win-exe] is recommended."
+"The Rust compiler currently must be built from a [tarball] or [git], unless "
+"you are on Windows, in which case using the [installer][win-exe] is "
+"recommended. There is a list of community-maintained nightly builds and "
+"packages [on the wiki][wiki-packages]."
 msgstr ""
 "Windows 以外の環境では、今のところ、Rust のコンパイラは [ソースコード]"
 "[tarball] からビルドする必要があります。Windows をお使いの場合は、 [インス"
 "トーラー][win-exe] の使用をおすすめします。"
 
 #. type: Plain text
-#: doc/tutorial.md:69
+#: doc/tutorial.md:72
+#, fuzzy
+#| msgid ""
+#| "Since the Rust compiler is written in Rust, it must be built by a "
+#| "precompiled \"snapshot\" version of itself (made in an earlier state of "
+#| "development). As such, source builds require a connection to the "
+#| "Internet, to fetch snapshots, and an OS that can execute the available "
+#| "snapshot binaries."
 msgid ""
 "Since the Rust compiler is written in Rust, it must be built by a "
 "precompiled \"snapshot\" version of itself (made in an earlier state of "
-"development). As such, source builds require a connection to the Internet, "
-"to fetch snapshots, and an OS that can execute the available snapshot "
-"binaries."
+"development). The source build automatically fetches these snapshots from "
+"the Internet on our supported platforms."
 msgstr ""
 "Rust のコンパイラは Rust で書かれているため、最新版の少し前のソースからコンパ"
 "イルされた「スナップショット」版コンパイラでビルドする必要があります。スナッ"
@@ -245,29 +249,29 @@ msgstr ""
 "す。"
 
 #. type: Plain text
-#: doc/tutorial.md:71
+#: doc/tutorial.md:74
 msgid "Snapshot binaries are currently built and tested on several platforms:"
 msgstr ""
 "スナップショットバイナリは、現時点では以下のプラットフォーム向けのものがあり"
 "ます。"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:75
+#: doc/tutorial.md:78
 msgid "Windows (7, Server 2008 R2), x86 only"
 msgstr "Windows (7, Server 2008 R2), x86 のみ"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:75
+#: doc/tutorial.md:78
 msgid "Linux (various distributions), x86 and x86-64"
 msgstr "Linux (各種ディストリビューション), x86 または x86-64"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:75
+#: doc/tutorial.md:78
 msgid "OSX 10.6 (\"Snow Leopard\") or greater, x86 and x86-64"
 msgstr "OSX 10.6 (\"Snow Leopard\") 以降, x86 または x86-64"
 
 #. type: Plain text
-#: doc/tutorial.md:78
+#: doc/tutorial.md:81
 msgid ""
 "You may find that other platforms work, but these are our \"tier 1\" "
 "supported build environments that are most likely to work."
@@ -276,7 +280,7 @@ msgstr ""
 "1\" プラットフォームとしてサポートされているのは上記のみです。"
 
 #. type: Plain text
-#: doc/tutorial.md:85
+#: doc/tutorial.md:88
 msgid ""
 "> ***Note:*** Windows users should read the detailed > \"[getting started]"
 "[wiki-start]\" notes on the wiki. Even when using > the binary installer, "
@@ -291,58 +295,68 @@ msgstr ""
 "ません。このような制限があることはは、本当に残念です。"
 
 #. type: Plain text
-#: doc/tutorial.md:88
+#: doc/tutorial.md:92
+#, fuzzy
+#| msgid ""
+#| "[bug-3319]: https://github.com/mozilla/rust/issues/3319 [wiki-start]: "
+#| "https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust"
 msgid ""
 "[bug-3319]: https://github.com/mozilla/rust/issues/3319 [wiki-start]: "
-"https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust"
+"https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust "
+"[git]: https://github.com/mozilla/rust.git"
 msgstr ""
 "[bug-3319]: https://github.com/mozilla/rust/issues/3319\n"
 "[wiki-start]: https://github.com/mozilla/rust/wiki/Note-getting-started-"
 "developing-Rust"
 
 #. type: Plain text
-#: doc/tutorial.md:91
+#: doc/tutorial.md:95
 msgid ""
 "To build from source you will also need the following prerequisite packages:"
 msgstr "ソースからビルドするためには、以下のパッケージが必要です。"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:97
+#: doc/tutorial.md:101
 msgid "g++ 4.4 or clang++ 3.x"
 msgstr "g++ 4.4 または clang++ 3.x"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:97
+#: doc/tutorial.md:101
 msgid "python 2.6 or later (but not 3.x)"
 msgstr "python 2.6 以降 (ただし、 3.x は除く)"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:97
+#: doc/tutorial.md:101
 msgid "perl 5.0 or later"
 msgstr "perl 5.0 以降"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:97
+#: doc/tutorial.md:101
 msgid "gnu make 3.81 or later"
 msgstr "gnu make 3.81 以降"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:97
+#: doc/tutorial.md:101
 msgid "curl"
 msgstr "curl"
 
 #. type: Plain text
-#: doc/tutorial.md:100
+#: doc/tutorial.md:104
 msgid ""
 "If you've fulfilled those prerequisites, something along these lines should "
 "work."
 msgstr "上記条件を満たしていれば、以下のような手順でビルド可能なはずです。"
 
 #. type: Plain text
-#: doc/tutorial.md:108
+#: doc/tutorial.md:112
+#, fuzzy
+#| msgid ""
+#| "~~~~ {.notrust} $ curl -O http://static.rust-lang.org/dist/rust-0.7.tar."
+#| "gz $ tar -xzf rust-0.7.tar.gz $ cd rust-0.7 $ ./configure $ make && make "
+#| "install ~~~~"
 msgid ""
-"~~~~ {.notrust} $ curl -O http://static.rust-lang.org/dist/rust-0.7.tar.gz $ "
-"tar -xzf rust-0.7.tar.gz $ cd rust-0.7 $ ./configure $ make && make install "
+"~~~~ {.notrust} $ curl -O http://static.rust-lang.org/dist/rust-0.9.tar.gz $ "
+"tar -xzf rust-0.9.tar.gz $ cd rust-0.9 $ ./configure $ make && make install "
 "~~~~"
 msgstr ""
 "~~~~ {.notrust}\n"
@@ -352,7 +366,7 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:114
+#: doc/tutorial.md:118
 msgid ""
 "You may need to use `sudo make install` if you do not normally have "
 "permission to modify the destination directory. The install locations can be "
@@ -365,11 +379,11 @@ msgstr ""
 "ポートしています。詳細については、 `--help` 引数を指定して実行してください。"
 
 #. type: Plain text
-#: doc/tutorial.md:120
+#: doc/tutorial.md:122
 msgid ""
 "When complete, `make install` will place several programs into `/usr/local/"
-"bin`: `rustc`, the Rust compiler; `rustdoc`, the API-documentation tool; "
-"and `rustpkg`, the Rust package manager."
+"bin`: `rustc`, the Rust compiler; `rustdoc`, the API-documentation tool; and "
+"`rustpkg`, the Rust package manager."
 msgstr ""
 "ビルド完了後、`make install` を実行すると、以下のプログラムが `/usr/local/"
 "bin` にインストールされます。\n"
@@ -379,21 +393,25 @@ msgstr ""
 "* `rustpkg`: Rust のパッケージマネージャ\n"
 
 #. type: Plain text
-#: doc/tutorial.md:123
+#: doc/tutorial.md:125
+#, fuzzy
+#| msgid ""
+#| "[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz [win-exe]: "
+#| "http://static.rust-lang.org/dist/rust-0.7-install.exe"
 msgid ""
-"[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz [win-exe]: "
-"http://static.rust-lang.org/dist/rust-0.7-install.exe"
+"[tarball]: http://static.rust-lang.org/dist/rust-0.9.tar.gz [win-exe]: "
+"http://static.rust-lang.org/dist/rust-0.9-install.exe"
 msgstr ""
 "[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz\n"
 "[win-exe]: http://static.rust-lang.org/dist/rust-0.7-install.exe"
 
 #. type: Plain text
-#: doc/tutorial.md:125
+#: doc/tutorial.md:127
 msgid "## Compiling your first program"
 msgstr "## 最初のプログラム"
 
 #. type: Plain text
-#: doc/tutorial.md:128
+#: doc/tutorial.md:130
 msgid ""
 "Rust program files are, by convention, given the extension `.rs`. Say we "
 "have a file `hello.rs` containing this program:"
@@ -402,18 +420,24 @@ msgstr ""
 "容を持つファイル、`hello.rs` が存在するとします。"
 
 #. type: Plain text
-#: doc/tutorial.md:134
-#, no-wrap
+#: doc/tutorial.md:136
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
 msgid ""
 "~~~~\n"
 "fn main() {\n"
-"    println(\"hello?\");\n"
+"    println!(\"hello?\");\n"
 "}\n"
 "~~~~\n"
 msgstr ""
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:138
+#: doc/tutorial.md:140
 msgid ""
 "If the Rust compiler was installed successfully, running `rustc hello.rs` "
 "will produce an executable called `hello` (or `hello.exe` on Windows) which, "
@@ -424,11 +448,17 @@ msgstr ""
 "が可能です。このファイルを実行すれば、予想通りの出力が得られるでしょう。"
 
 #. type: Plain text
-#: doc/tutorial.md:143
+#: doc/tutorial.md:145
+#, fuzzy
+#| msgid ""
+#| "The Rust compiler tries to provide useful information when it encounters "
+#| "an error. If you introduce an error into the program (for example, by "
+#| "changing `println` to some nonexistent function), and then compile it, "
+#| "you'll see an error message like this:"
 msgid ""
 "The Rust compiler tries to provide useful information when it encounters an "
 "error. If you introduce an error into the program (for example, by changing "
-"`println` to some nonexistent function), and then compile it, you'll see an "
+"`println!` to some nonexistent macro), and then compile it, you'll see an "
 "error message like this:"
 msgstr ""
 "コンパイルエラーが発生した場合、Rust コンパイラはエラー解決のための情報を出力"
@@ -437,25 +467,22 @@ msgstr ""
 "が出力されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:149
-#, no-wrap
-msgid ""
-"~~~~ {.notrust}\n"
-"hello.rs:2:4: 2:16 error: unresolved name: print_with_unicorns\n"
-"hello.rs:2     print_with_unicorns(\"hello?\");\n"
-"               ^~~~~~~~~~~~~~~~~~~~~~~\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:156
+#: doc/tutorial.md:158
+#, fuzzy
+#| msgid ""
+#| "In its simplest form, a Rust program is a `.rs` file with some types and "
+#| "functions defined in it. If it has a `main` function, it can be compiled "
+#| "to an executable. Rust does not allow code that's not a declaration to "
+#| "appear at the top level of the file: all statements must live inside a "
+#| "function.  Rust programs can also be compiled as libraries, and included "
+#| "in other programs."
 msgid ""
 "In its simplest form, a Rust program is a `.rs` file with some types and "
 "functions defined in it. If it has a `main` function, it can be compiled to "
 "an executable. Rust does not allow code that's not a declaration to appear "
 "at the top level of the file: all statements must live inside a function.  "
 "Rust programs can also be compiled as libraries, and included in other "
-"programs."
+"programs, even ones not written in Rust."
 msgstr ""
 "最も単純な Rust プログラムは、いくつかの型や関数が定義された `.rs` ファイルの"
 "みからなります。`.rs` ファイルをコンパイルして実行可能ファイルを作成する場"
@@ -465,54 +492,12 @@ msgstr ""
 "プログラムから利用するライブラリとしてコンパイルすることも可能です。"
 
 #. type: Plain text
-#: doc/tutorial.md:158
-msgid "## Using the rust tool"
-msgstr "## `rust` コマンドを利用する"
-
-#. type: Plain text
-#: doc/tutorial.md:163
-msgid ""
-"While using `rustc` directly to generate your executables, and then running "
-"them manually is a perfectly valid way to test your code, for smaller "
-"projects, prototypes, or if you're a beginner, it might be more convenient "
-"to use the `rust` tool."
-msgstr ""
-"作成したプログラムのテストを行うには、`rustc` でコンパイル後、生成されたファ"
-"イルを手動で実行する方法だけではなく、 `rust` ツールを利用する方法もありま"
-"す。小さなプロジェクトやプロトタイプを作成する場合、もしくはあなたが初心者の"
-"場合は、 `rust` ツールによりコンパイルから実行までの一連の流れを簡単に行うこ"
-"とができます。"
-
-#. type: Plain text
-#: doc/tutorial.md:169
-msgid ""
-"The `rust` tool provides central access to the other Rust tools, as well as "
-"handy shortcuts for directly running source files.  For example, if you have "
-"a file `foo.rs` in your current directory, `rust run foo.rs` would attempt "
-"to compile it and, if successful, directly run the resulting binary."
-msgstr ""
-"`rust` ツールには、Rust ツール群を統一的なインターフェースで呼び出す機能だけ"
-"でなく、ソースファイルを直接実行する便利なショートカット機能もあります。例え"
-"ば、カレントディレクトリにある `foo.rs` を実行しようとする場合、 `rust run "
-"foo.rs` を実行することで、コンパイルから、コンパイル成功後に生成されるバイナ"
-"リの実行までを自動的に行なってくれます。"
-
-#. type: Plain text
-#: doc/tutorial.md:172
-msgid ""
-"To get a list of all available commands, simply call `rust` without any "
-"argument."
-msgstr ""
-"実行可能なコマンドを調べるためには、引数を与えず `rust` コマンドを実行してく"
-"ださい。"
-
-#. type: Plain text
-#: doc/tutorial.md:174
+#: doc/tutorial.md:160
 msgid "## Editing Rust code"
 msgstr "## Rust のコードを編集する"
 
 #. type: Plain text
-#: doc/tutorial.md:184
+#: doc/tutorial.md:170
 msgid ""
 "There are vim highlighting and indentation scripts in the Rust source "
 "distribution under `src/etc/vim/`. There is an emacs mode under `src/etc/"
@@ -533,7 +518,7 @@ msgstr ""
 "etc/kate` 以下です。"
 
 #. type: Plain text
-#: doc/tutorial.md:188
+#: doc/tutorial.md:177
 msgid ""
 "There is ctags support via `src/etc/ctags.rust`, but many other tools and "
 "editors are not yet supported. If you end up writing a Rust mode for your "
@@ -544,7 +529,7 @@ msgstr ""
 "ディタ向けのRust モードを作成した場合、リンクを貼りたいのでお知らせください。"
 
 #. type: Plain text
-#: doc/tutorial.md:191
+#: doc/tutorial.md:180
 msgid ""
 "[sublime]: http://github.com/dbp/sublime-rust [sublime-pkg]: http://wbond."
 "net/sublime_packages/package_control"
@@ -553,12 +538,12 @@ msgstr ""
 "[sublime-pkg]: http://wbond.net/sublime_packages/package_control"
 
 #. type: Plain text
-#: doc/tutorial.md:193
+#: doc/tutorial.md:182
 msgid "# Syntax basics"
 msgstr "# 基本的な構文"
 
 #. type: Plain text
-#: doc/tutorial.md:201
+#: doc/tutorial.md:190
 msgid ""
 "Assuming you've programmed in any C-family language (C++, Java, JavaScript, "
 "C#, or PHP), Rust will feel familiar. Code is arranged in blocks delineated "
@@ -576,7 +561,7 @@ msgstr ""
 "レータは C++ と同様 2つのコロン (`::`) です。"
 
 #. type: Plain text
-#: doc/tutorial.md:206
+#: doc/tutorial.md:195
 msgid ""
 "The main surface difference to be aware of is that the condition at the head "
 "of control structures like `if` and `while` does not require parentheses, "
@@ -589,7 +574,7 @@ msgstr ""
 "とはできません。"
 
 #. type: Plain text
-#: doc/tutorial.md:219
+#: doc/tutorial.md:208
 #, no-wrap
 msgid ""
 "~~~~\n"
@@ -619,7 +604,7 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:223
+#: doc/tutorial.md:212
 msgid ""
 "The `let` keyword introduces a local variable. Variables are immutable by "
 "default. To introduce a local variable that you can re-assign later, use "
@@ -630,7 +615,7 @@ msgstr ""
 "mut` を用います。"
 
 #. type: Plain text
-#: doc/tutorial.md:227
+#: doc/tutorial.md:216
 msgid "~~~~ let hi = \"hi\"; let mut count = 0;"
 msgstr ""
 "~~~~\n"
@@ -638,32 +623,27 @@ msgstr ""
 " let mut count = 0;"
 
 #. type: Plain text
-#: doc/tutorial.md:233
-#, no-wrap
-msgid ""
-"while count < 10 {\n"
-"    println(fmt!(\"count: %?\", count));\n"
-"    count += 1;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:237
+#: doc/tutorial.md:226
+#, fuzzy
+#| msgid ""
+#| "Although Rust can almost always infer the types of local variables, you "
+#| "can specify a variable's type by following it with a colon, then the type "
+#| "name. Static items, on the other hand, always require a type annotation."
 msgid ""
 "Although Rust can almost always infer the types of local variables, you can "
-"specify a variable's type by following it with a colon, then the type name. "
-"Static items, on the other hand, always require a type annotation."
+"specify a variable's type by following it in the `let` with a colon, then "
+"the type name. Static items, on the other hand, always require a type "
+"annotation."
 msgstr ""
 "Rust は、ほぼすべてのローカル変数の型を推論してくれますが、コロンの後に続けて"
 "型名を書くことで、明示的に変数の型を指定することもできます。一方、静的な項目 "
 "(static item) には、常に型注釈を指定しなければなりません。"
 
 #. type: Plain text
-#: doc/tutorial.md:243
+#: doc/tutorial.md:233
 msgid ""
-"~~~~ static MONSTER_FACTOR: f64 = 57.8; let monster_size = MONSTER_FACTOR "
-"10.0; let monster_size: int = 50; ~~~~"
+"~~~~ static MONSTER_FACTOR: f64 = 57.8; let monster_size = MONSTER_FACTOR "
+"10.0; let monster_size: int = 50; ~~~~"
 msgstr ""
 "~~~~\n"
 "static MONSTER_FACTOR: f64 = 57.8;\n"
@@ -672,7 +652,7 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:252
+#: doc/tutorial.md:242
 msgid ""
 "Local variables may shadow earlier declarations, as in the previous example: "
 "`monster_size` was first declared as a `f64`, and then a second "
@@ -684,15 +664,15 @@ msgid ""
 "the warning, like `let _monster_size = 50;`."
 msgstr ""
 "ローカル変数は、先行する宣言を隠すことがあります。先の例では、1つ目の "
-"`monster_size` は `f64` として宣言され、2つ目の `monster_size` は `int` と"
-"ã\81\97ã\81¦å®£è¨\80ã\81\95ã\82\8cã\81¦ã\81\84ã\81¾ã\81\99ã\80\82ã\81\93ã\81®ã\83\97ã\83­ã\82°ã\83©ã\83 ã\82\92ã\82³ã\83³ã\83\91ã\82¤ã\83«ã\81\97ã\81\9få ´å\90\88ã\80\81ã\80\8c\81¤ç\9b®ã\81® "
+"`monster_size` は `f64` として宣言され、2つ目の `monster_size` は `int` と"
+"て宣言されています。このプログラムをコンパイルした場合、「1つ目の "
 "`monster_size` は未使用である」という警告メッセージが出力されます (プログラマ"
 "が何らかの誤りを犯している可能性があるため)。未使用変数の存在が意図的なもので"
 "あった場合、未使用変数名の先頭にアンダースコアをつけることで、警告を抑制でき"
 "ます (`let _monster_size = 50;`)。"
 
 #. type: Plain text
-#: doc/tutorial.md:258
+#: doc/tutorial.md:248
 msgid ""
 "Rust identifiers start with an alphabetic character or an underscore, and "
 "after that may contain any sequence of alphabetic characters, numbers, or "
@@ -707,7 +687,7 @@ msgstr ""
 "されています。"
 
 #. type: Plain text
-#: doc/tutorial.md:263
+#: doc/tutorial.md:253
 #, no-wrap
 msgid ""
 "~~~\n"
@@ -721,12 +701,12 @@ msgstr ""
 "~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:265
+#: doc/tutorial.md:255
 msgid "## Expressions and semicolons"
 msgstr "## 式とセミコロン"
 
 #. type: Plain text
-#: doc/tutorial.md:271
+#: doc/tutorial.md:261
 msgid ""
 "Though it isn't apparent in all code, there is a fundamental difference "
 "between Rust's syntax and predecessors like C.  Many constructs that are "
@@ -740,46 +720,12 @@ msgstr ""
 "ようにコードを書きますが、"
 
 #. type: Plain text
-#: doc/tutorial.md:283
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# let item = \"salad\";\n"
-"let price;\n"
-"if item == \"salad\" {\n"
-"    price = 3.50;\n"
-"} else if item == \"muffin\" {\n"
-"    price = 2.25;\n"
-"} else {\n"
-"    price = 2.00;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:285
+#: doc/tutorial.md:275
 msgid "But, in Rust, you don't have to repeat the name `price`:"
 msgstr "Rust では、変数名 `price` を繰り返し書く必要はありません。"
 
 #. type: Plain text
-#: doc/tutorial.md:297
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# let item = \"salad\";\n"
-"let price =\n"
-"    if item == \"salad\" {\n"
-"        3.50\n"
-"    } else if item == \"muffin\" {\n"
-"        2.25\n"
-"    } else {\n"
-"        2.00\n"
-"    };\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:303
+#: doc/tutorial.md:293
 msgid ""
 "Both pieces of code are exactly equivalent: they assign a value to `price` "
 "depending on the condition that holds. Note that there are no semicolons in "
@@ -794,7 +740,7 @@ msgstr ""
 "最後の式の値になります**。"
 
 #. type: Plain text
-#: doc/tutorial.md:309
+#: doc/tutorial.md:299
 msgid ""
 "Put another way, the semicolon in Rust *ignores the value of an "
 "expression*.  Thus, if the branches of the `if` had looked like `{ 4; }`, "
@@ -809,7 +755,7 @@ msgstr ""
 "には節のうち実行されたものの値が代入されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:314
+#: doc/tutorial.md:304
 msgid ""
 "In short, everything that's not a declaration (declarations are `let` for "
 "variables; `fn` for functions; and any top-level named items such as [traits]"
@@ -821,7 +767,7 @@ msgstr ""
 "すべてが式となります。関数のボディ部も式です。"
 
 #. type: Plain text
-#: doc/tutorial.md:322
+#: doc/tutorial.md:312
 #, no-wrap
 msgid ""
 "~~~~\n"
@@ -840,19 +786,19 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:324
+#: doc/tutorial.md:314
 msgid "## Primitive types and literals"
 msgstr "## プリミティブ型とリテラル"
 
 #. type: Plain text
-#: doc/tutorial.md:331
+#: doc/tutorial.md:321
 msgid ""
 "There are general signed and unsigned integer types, `int` and `uint`, as "
 "well as 8-, 16-, 32-, and 64-bit variants, `i8`, `u16`, etc.  Integers can "
-"be written in decimal (`144`), hexadecimal (`0x90`), octal (`0o70`), or binary "
-"(`0b10010000`) base. Each integral type has a corresponding literal suffix "
-"that can be used to indicate the type of a literal: `i` for `int`, `u` for "
-"`uint`, `i8` for the `i8` type."
+"be written in decimal (`144`), hexadecimal (`0x90`), octal (`0o70`), or "
+"binary (`0b10010000`) base. Each integral type has a corresponding literal "
+"suffix that can be used to indicate the type of a literal: `i` for `int`, "
+"`u` for `uint`, `i8` for the `i8` type."
 msgstr ""
 "Rust には、他の言語と同様、符号付き整数の `int` と、符号なし整数の `uint` が"
 "あります。同様に、8 または 16, 32, 64 ビット幅の `i8`, `u16` などもあります。"
@@ -862,7 +808,7 @@ msgstr ""
 "応します。"
 
 #. type: Plain text
-#: doc/tutorial.md:337
+#: doc/tutorial.md:327
 msgid ""
 "In the absence of an integer literal suffix, Rust will infer the integer "
 "type based on type annotations and function signatures in the surrounding "
@@ -874,7 +820,7 @@ msgstr ""
 "フィックスなしの整数リテラルは `int` 型だとみなされます。"
 
 #. type: Plain text
-#: doc/tutorial.md:344
+#: doc/tutorial.md:334
 #, no-wrap
 msgid ""
 "~~~~\n"
@@ -892,33 +838,47 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:349
+#: doc/tutorial.md:339
+#, fuzzy
+#| msgid ""
+#| "There are two floating-point types: `f32`, and `f64`. Floating-point "
+#| "numbers are written `0.0`, `1e6`, or `2.1e-4`. Like integers, floating-"
+#| "point literals are inferred to the correct type. Suffixes `f32`, and "
+#| "`f64` can be used to create literals of a specific type."
 msgid ""
-"There are two floating-point types: `f32`, and `f64`. Floating-"
-"point numbers are written `0.0`, `1e6`, or `2.1e-4`. Like integers, "
-"floating-point literals are inferred to the correct type. Suffixes "
-"`f32`, and `f64` can be used to create literals of a specific type."
+"There are two floating-point types: `f32`, and `f64`.  Floating-point "
+"numbers are written `0.0`, `1e6`, or `2.1e-4`.  Like integers, floating-"
+"point literals are inferred to the correct type.  Suffixes `f32`, and `f64` "
+"can be used to create literals of a specific type."
 msgstr ""
-"浮動小数型は、 `f32`, `f64` の2種類があります。浮動小数リテラルは "
-"`0.0` や、 `1e6`、 `2.1e-4` といった表記が可能です。整数と同じく、サフィック"
-"ã\82¹ã\81\8cç\9c\81ç\95¥ã\81\95ã\82\8cã\81\9fæµ®å\8b\95å°\8fæ\95°ã\83ªã\83\86ã\83©ã\83«ã\81¯å\9e\8bæ\8e¨è«\96ã\81\95ã\82\8cã\81¾ã\81\99ã\80\82æµ®å\8b\95å°\8fæ\95°ã\81®ã\82µã\83\95ã\82£ã\83\83ã\82¯ã\82¹ã\81¯ "
-"`f32`、`f64` の3種類で、リテラルの末尾につけることで、対応する型の値を作"
-"ã\82\8aå\87ºã\81\99ã\81\93ã\81¨ã\81\8cã\81§ã\81\8dã\81¾ã\81\99ã\80\82"
+"浮動小数型は、 `f32`, `f64` の2種類があります。浮動小数リテラルは `0.0` や、 "
+"`1e6`、 `2.1e-4` といった表記が可能です。整数と同じく、サフィックスが省略され"
+"ã\81\9fæµ®å\8b\95å°\8fæ\95°ã\83ªã\83\86ã\83©ã\83«ã\81¯å\9e\8bæ\8e¨è«\96ã\81\95ã\82\8cã\81¾ã\81\99ã\80\82æµ®å\8b\95å°\8fæ\95°ã\81®ã\82µã\83\95ã\82£ã\83\83ã\82¯ã\82¹ã\81¯ `f32`ã\80\81`f64` ã\81®3"
+"種類で、リテラルの末尾につけることで、対応する型の値を作り出すことができま"
+"す。"
 
 #. type: Plain text
-#: doc/tutorial.md:351
+#: doc/tutorial.md:341
 msgid "The keywords `true` and `false` produce literals of type `bool`."
 msgstr "`true` キーワードと `false` キーワードは、`bool` 型のリテラルです。"
 
 #. type: Plain text
-#: doc/tutorial.md:358
+#: doc/tutorial.md:348
+#, fuzzy
+#| msgid ""
+#| "Characters, the `char` type, are four-byte Unicode codepoints, whose "
+#| "literals are written between single quotes, as in `'x'`.  Just like C, "
+#| "Rust understands a number of character escapes, using the backslash "
+#| "character, such as `\\n`, `\\r`, and `\\t`. String literals, written "
+#| "between double quotes, allow the same escape sequences.  More on strings "
+#| "[later](#vectors-and-strings)."
 msgid ""
 "Characters, the `char` type, are four-byte Unicode codepoints, whose "
 "literals are written between single quotes, as in `'x'`.  Just like C, Rust "
 "understands a number of character escapes, using the backslash character, "
 "such as `\\n`, `\\r`, and `\\t`. String literals, written between double "
-"quotes, allow the same escape sequences.  More on strings [later](#vectors-"
-"and-strings)."
+"quotes, allow the same escape sequences, and do no other processing, unlike "
+"languages such as PHP or shell."
 msgstr ""
 "文字は `char` 型で表され、4バイトの Unicode コードポイントに対応しています。"
 "`'x'` のように、文字をシングルクオートで囲んだものが文字リテラルです。C と同"
@@ -928,18 +888,18 @@ msgstr ""
 "タと文字列) の章で述べます。"
 
 #. type: Plain text
-#: doc/tutorial.md:360
+#: doc/tutorial.md:356
 msgid "The nil type, written `()`, has a single value, also written `()`."
 msgstr ""
 "nil 型は `()` と表記されます。 nil 型の唯一の値も `()` と表記されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:362
+#: doc/tutorial.md:358
 msgid "## Operators"
 msgstr "## 演算子"
 
 #. type: Plain text
-#: doc/tutorial.md:367
+#: doc/tutorial.md:363
 msgid ""
 "Rust's set of operators contains very few surprises. Arithmetic is done with "
 "`*`, `/`, `%`, `+`, and `-` (multiply, quotient, remainder, add, and "
@@ -952,16 +912,20 @@ msgstr ""
 "ポートされています。"
 
 #. type: Plain text
-#: doc/tutorial.md:370
+#: doc/tutorial.md:366
+#, fuzzy
+#| msgid ""
+#| "Note that, if applied to an integer value, `!` flips all the bits (like "
+#| "`~` in C)."
 msgid ""
-"Note that, if applied to an integer value, `!` flips all the bits (like `~` "
-"in C)."
+"Note that, if applied to an integer value, `!` flips all the bits (bitwise "
+"NOT, like `~` in C)."
 msgstr ""
 "整数型に対して `!` 演算子を適用すると、ビット単位での反転操作 (C の `~` と同"
 "じ動作) が行われることに注意してください。"
 
 #. type: Plain text
-#: doc/tutorial.md:374
+#: doc/tutorial.md:370
 msgid ""
 "The comparison operators are the traditional `==`, `!=`, `<`, `>`, `<=`, and "
 "`>=`. Short-circuiting (lazy) boolean operators are written `&&` (and) and "
@@ -972,21 +936,28 @@ msgstr ""
 "ります。"
 
 #. type: Plain text
-#: doc/tutorial.md:379
+#: doc/tutorial.md:377
+#, fuzzy
+#| msgid ""
+#| "For type casting, Rust uses the binary `as` operator.  It takes an "
+#| "expression on the left side and a type on the right side and will, if a "
+#| "meaningful conversion exists, convert the result of the expression to the "
+#| "given type."
 msgid ""
-"For type casting, Rust uses the binary `as` operator.  It takes an "
-"expression on the left side and a type on the right side and will, if a "
+"For compile-time type casting, Rust uses the binary `as` operator.  It takes "
+"an expression on the left side and a type on the right side and will, if a "
 "meaningful conversion exists, convert the result of the expression to the "
-"given type."
+"given type. Generally, `as` is only used with the primitive numeric types or "
+"pointers, and is not overloadable.  [`transmute`][transmute] can be used for "
+"unsafe C-like casting of same-sized types."
 msgstr ""
 "Rust では、型のキャストには二項演算子 `as` を使います。`as` 演算子は、左辺に"
 "式、右辺に型を取り、意味のある変換が可能な場合に限り、式の評価結果を指定され"
 "た型に変換します。"
 
 #. type: Plain text
-#: doc/tutorial.md:385
-msgid ""
-"~~~~ let x: f64 = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
+#: doc/tutorial.md:383
+msgid "~~~~ let x: f64 = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
 msgstr ""
 "~~~~\n"
 "let x: f64 = 4.0;\n"
@@ -994,82 +965,121 @@ msgstr ""
 "assert!(y == 4u);\n"
 "~~~~"
 
+#. type: Plain text
+#: doc/tutorial.md:385
+#, fuzzy
+#| msgid ""
+#| "[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz [win-exe]: "
+#| "http://static.rust-lang.org/dist/rust-0.7-install.exe"
+msgid ""
+"[transmute]: http://static.rust-lang.org/doc/master/std/cast/fn.transmute."
+"html"
+msgstr ""
+"[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz\n"
+"[win-exe]: http://static.rust-lang.org/dist/rust-0.7-install.exe"
+
 #. type: Plain text
 #: doc/tutorial.md:387
 msgid "## Syntax extensions"
 msgstr "## 構文拡張"
 
 #. type: Plain text
-#: doc/tutorial.md:394
-#, no-wrap
+#: doc/tutorial.md:395
+#, fuzzy, no-wrap
+#| msgid ""
+#| "*Syntax extensions* are special forms that are not built into the language,\n"
+#| "but are instead provided by the libraries. To make it clear to the reader when\n"
+#| "a name refers to a syntax extension, the names of all syntax extensions end\n"
+#| "with `!`. The standard library defines a few syntax extensions, the most\n"
+#| "useful of which is `fmt!`, a `sprintf`-style text formatter that you will\n"
+#| "often see in examples.\n"
 msgid ""
 "*Syntax extensions* are special forms that are not built into the language,\n"
 "but are instead provided by the libraries. To make it clear to the reader when\n"
 "a name refers to a syntax extension, the names of all syntax extensions end\n"
 "with `!`. The standard library defines a few syntax extensions, the most\n"
-"useful of which is `fmt!`, a `sprintf`-style text formatter that you will\n"
-"often see in examples.\n"
+"useful of which is [`format!`][fmt], a `sprintf`-like text formatter that you\n"
+"will often see in examples, and its related family of macros: `print!`,\n"
+"`println!`, and `write!`.\n"
 msgstr "**構文拡張** *(Syntax extensions)* は言語組み込みではなく、ライブラリにより提供される特殊形式 (スペシャルフォーム) です。プログラム中に構文拡張が登場したことを外見上明確にするため、構文拡張の名前には末尾に `!` をつけますなければなりません。標準ライブラリではいくつかの構文拡張が定義されていますが、その中でも最も有用なのは `fmt!` です。`fmt!` は `sprintf`スタイルの書式整形を行うもので、後のコード例の中でも何度か見かけることになるでしょう。\n"
 
 #. type: Plain text
-#: doc/tutorial.md:398
+#: doc/tutorial.md:399
+#, fuzzy
+#| msgid ""
+#| "`fmt!` supports most of the directives that [printf][pf] supports, but "
+#| "unlike printf, will give you a compile-time error when the types of the "
+#| "directives don't match the types of the arguments."
 msgid ""
-"`fmt!` supports most of the directives that [printf][pf] supports, but "
-"unlike printf, will give you a compile-time error when the types of the "
-"directives don't match the types of the arguments."
+"`format!` draws syntax from Python, but contains many of the same principles "
+"that [printf][pf] has. Unlike printf, `format!` will give you a compile-time "
+"error when the types of the directives don't match the types of the "
+"arguments."
 msgstr ""
 "`fmt!` は、[`printf`][pf] がサポートするほとんどのディレクティブ (フォーマッ"
 "ト指定子) をサポートしますが、`printf` とは異なり、ディレクティブと引数の型が"
 "一致しない場合はコンパイルエラーとなります。"
 
 #. type: Plain text
-#: doc/tutorial.md:401
+#: doc/tutorial.md:402
 msgid "~~~~ # let mystery_object = ();"
 msgstr ""
 "~~~~\n"
 "# let mystery_object = ();"
 
 #. type: Plain text
-#: doc/tutorial.md:403
-msgid "println(fmt!(\"%s is %d\", \"the answer\", 43));"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:407
+#: doc/tutorial.md:409
+#, fuzzy
+#| msgid ""
+#| "// %? will conveniently print any type println(fmt!(\"what is this thing: "
+#| "%?\", mystery_object)); ~~~~"
 msgid ""
-"// %? will conveniently print any type println(fmt!(\"what is this thing: %?"
-"\", mystery_object)); ~~~~"
+"// {:?} will conveniently print any type println!(\"what is this thing: "
+"{:?}\", mystery_object); ~~~~"
 msgstr ""
 "// %? は任意の型を表示できる便利なディレクティブです\n"
 "println(fmt!(\"what is this thing: %?\", mystery_object));\n"
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:409
-msgid "[pf]: http://en.cppreference.com/w/cpp/io/c/fprintf"
+#: doc/tutorial.md:412
+#, fuzzy
+#| msgid ""
+#| "[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz [win-exe]: "
+#| "http://static.rust-lang.org/dist/rust-0.7-install.exe"
+msgid ""
+"[pf]: http://en.cppreference.com/w/cpp/io/c/fprintf [fmt]: http://static."
+"rust-lang.org/doc/master/std/fmt/index.html"
 msgstr ""
+"[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz\n"
+"[win-exe]: http://static.rust-lang.org/dist/rust-0.7-install.exe"
 
 #. type: Plain text
-#: doc/tutorial.md:411
+#: doc/tutorial.md:416
+#, fuzzy
+#| msgid ""
+#| "You can define your own syntax extensions with the macro system. For "
+#| "details, see the [macro tutorial][macros]."
 msgid ""
 "You can define your own syntax extensions with the macro system. For "
-"details, see the [macro tutorial][macros]."
+"details, see the [macro tutorial][macros]. Note that macro definition is "
+"currently considered an unstable feature."
 msgstr ""
 "マクロシステムを利用すれば、独自に構文拡張を定義することも可能です。詳細は "
 "[マクロチュートリアル][macros] を参照してください。"
 
 #. type: Plain text
-#: doc/tutorial.md:413
+#: doc/tutorial.md:418
 msgid "# Control structures"
 msgstr "# 制御構造"
 
 #. type: Plain text
-#: doc/tutorial.md:415
+#: doc/tutorial.md:420
 msgid "## Conditionals"
 msgstr "## 条件式"
 
 #. type: Plain text
-#: doc/tutorial.md:419
+#: doc/tutorial.md:424
 msgid ""
 "We've seen `if` expressions a few times already. To recap, braces are "
 "compulsory, an `if` can have an optional `else` clause, and multiple `if`/"
@@ -1080,22 +1090,7 @@ msgstr ""
 "構文は互いに連鎖できる、ということでした。"
 
 #. type: Plain text
-#: doc/tutorial.md:429
-#, no-wrap
-msgid ""
-"~~~~\n"
-"if false {\n"
-"    println(\"that's odd\");\n"
-"} else if true {\n"
-"    println(\"right\");\n"
-"} else {\n"
-"    println(\"neither true nor false\");\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:434
+#: doc/tutorial.md:439
 msgid ""
 "The condition given to an `if` construct *must* be of type `bool` (no "
 "implicit conversion happens). If the arms are blocks that have a value, this "
@@ -1107,25 +1102,12 @@ msgstr ""
 "るものは、すべて同じ型の値でなければなりません。"
 
 #. type: Plain text
-#: doc/tutorial.md:442
-#, no-wrap
-msgid ""
-"~~~~\n"
-"fn signum(x: int) -> int {\n"
-"    if x < 0 { -1 }\n"
-"    else if x > 0 { 1 }\n"
-"    else { return 0 }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:444
+#: doc/tutorial.md:449
 msgid "## Pattern matching"
 msgstr "## パターンマッチ"
 
 #. type: Plain text
-#: doc/tutorial.md:450
+#: doc/tutorial.md:455
 msgid ""
 "Rust's `match` construct is a generalized, cleaned-up version of C's "
 "`switch` construct. You provide it with a value and a number of *arms*, each "
@@ -1142,22 +1124,7 @@ msgstr ""
 "ターンとの比較は行われません。"
 
 #. type: Plain text
-#: doc/tutorial.md:460
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# let my_number = 1;\n"
-"match my_number {\n"
-"  0     => println(\"zero\"),\n"
-"  1 | 2 => println(\"one or two\"),\n"
-"  3..10 => println(\"three to ten\"),\n"
-"  _     => println(\"something else\")\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:464
+#: doc/tutorial.md:469
 msgid ""
 "Unlike in C, there is no \"falling through\" between arms: only one arm "
 "executes, and it doesn't have to explicitly `break` out of the construct "
@@ -1168,7 +1135,17 @@ msgstr ""
 "する必要はありません。"
 
 #. type: Plain text
-#: doc/tutorial.md:474
+#: doc/tutorial.md:478
+#, fuzzy
+#| msgid ""
+#| "A `match` arm consists of a *pattern*, then an arrow `=>`, followed by an "
+#| "*action* (expression). Literals are valid patterns and match only their "
+#| "own value. A single arm may match multiple different patterns by "
+#| "combining them with the pipe operator (`|`), so long as every pattern "
+#| "binds the same set of variables. Ranges of numeric literal patterns can "
+#| "be expressed with two dots, as in `M..N`. The underscore (`_`) is a "
+#| "wildcard pattern that matches any single value. The asterisk (`*`)  is a "
+#| "different wildcard that can match one or more fields in an `enum` variant."
 msgid ""
 "A `match` arm consists of a *pattern*, then an arrow `=>`, followed by an "
 "*action* (expression). Literals are valid patterns and match only their own "
@@ -1176,8 +1153,8 @@ msgid ""
 "with the pipe operator (`|`), so long as every pattern binds the same set of "
 "variables. Ranges of numeric literal patterns can be expressed with two "
 "dots, as in `M..N`. The underscore (`_`) is a wildcard pattern that matches "
-"any single value. The asterisk (`*`)  is a different wildcard that can match "
-"one or more fields in an `enum` variant."
+"any single value. (`..`) is a different wildcard that can match one or more "
+"fields in an `enum` variant."
 msgstr ""
 "`match` の arm は、 **パターン** および矢印 `=>` と、それらに続く **アクショ"
 "ン** (式) から構成されます。リテラルはパターンとして利用可能で、リテラル自身"
@@ -1193,7 +1170,7 @@ msgstr ""
 "す)。"
 
 #. type: Plain text
-#: doc/tutorial.md:479
+#: doc/tutorial.md:483
 msgid ""
 "The patterns in a match arm are followed by a fat arrow, `=>`, then an "
 "expression to evaluate. Each case is separated by commas. It's often "
@@ -1204,20 +1181,7 @@ msgstr ""
 "を記述することも可能で、その場合は arm 末尾のカンマを省略することが可能です。"
 
 #. type: Plain text
-#: doc/tutorial.md:487
-#, no-wrap
-msgid ""
-"~~~\n"
-"# let my_number = 1;\n"
-"match my_number {\n"
-"  0 => { println(\"zero\") }\n"
-"  _ => { println(\"something else\") }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:492
+#: doc/tutorial.md:496
 msgid ""
 "`match` constructs must be *exhaustive*: they must have an arm covering "
 "every possible case. For example, the typechecker would reject the previous "
@@ -1229,7 +1193,7 @@ msgstr ""
 "ンの arm を削除した場合、型検査によりコンパイルエラーとされます。"
 
 #. type: Plain text
-#: doc/tutorial.md:496
+#: doc/tutorial.md:500
 msgid ""
 "A powerful application of pattern matching is *destructuring*: matching in "
 "order to bind names to the contents of data types."
@@ -1238,39 +1202,28 @@ msgstr ""
 "造化代入とは、データ型内部の値を名前に束縛 (bind) することです。"
 
 #. type: Plain text
-#: doc/tutorial.md:500
-msgid ""
-"> ***Note:*** The following code makes use of tuples (`(f64, f64)`) "
-"which > are explained in section 5.3. For now you can think of tuples as a "
-"list of > items."
-msgstr ""
-"> ***注意:*** 以下のコード例では5.3 節で説明されるタプル (`(f64, f64)`) "
-"を使っています。現時点では、タプルは項目のリストのようなものだとみなしてくだ"
-"さい。"
-
-#. type: Plain text
-#: doc/tutorial.md:513
-#, no-wrap
+#: doc/tutorial.md:504
 msgid ""
-"~~~~\n"
-"use std::f64;\n"
-"use std::num::atan;\n"
-"fn angle(vector: (f64, f64)) -> f64 {\n"
-"    let pi = f64::consts::pi;\n"
-"    match vector {\n"
-"      (0f, y) if y < 0f => 1.5 * pi,\n"
-"      (0f, y) => 0.5 * pi,\n"
-"      (x, y) => atan(y / x)\n"
-"    }\n"
-"}\n"
-"~~~~\n"
+"> ***Note:*** The following code makes use of tuples (`(f64, f64)`) which > "
+"are explained in section 5.3. For now you can think of tuples as a list of > "
+"items."
 msgstr ""
+"> ***注意:*** 以下のコード例では5.3 節で説明されるタプル (`(f64, f64)`) を"
+"使っています。現時点では、タプルは項目のリストのようなものだとみなしてくださ"
+"い。"
 
 #. type: Plain text
-#: doc/tutorial.md:519
+#: doc/tutorial.md:523
+#, fuzzy
+#| msgid ""
+#| "A variable name in a pattern matches any value, *and* binds that name to "
+#| "the value of the matched value inside of the arm's action. Thus, `(0f, "
+#| "y)` matches any tuple whose first element is zero, and binds `y` to the "
+#| "second element. `(x, y)` matches any two-element tuple, and binds both "
+#| "elements to variables."
 msgid ""
 "A variable name in a pattern matches any value, *and* binds that name to the "
-"value of the matched value inside of the arm's action. Thus, `(0f, y)` "
+"value of the matched value inside of the arm's action. Thus, `(0.0, y)` "
 "matches any tuple whose first element is zero, and binds `y` to the second "
 "element. `(x, y)` matches any two-element tuple, and binds both elements to "
 "variables."
@@ -1282,7 +1235,7 @@ msgstr ""
 "数に束縛されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:526
+#: doc/tutorial.md:530
 msgid ""
 "Any `match` arm can have a guard clause (written `if EXPR`), called a "
 "*pattern guard*, which is an expression of type `bool` that determines, "
@@ -1298,7 +1251,7 @@ msgstr ""
 "用例が示されています。"
 
 #. type: Plain text
-#: doc/tutorial.md:531
+#: doc/tutorial.md:535
 msgid ""
 "You've already seen simple `let` bindings, but `let` is a little fancier "
 "than you've been led to believe. It, too, supports destructuring patterns. "
@@ -1310,7 +1263,7 @@ msgstr ""
 "定義することが可能です。"
 
 #. type: Plain text
-#: doc/tutorial.md:536
+#: doc/tutorial.md:540
 msgid ""
 "~~~~ # fn get_tuple_of_two_ints() -> (int, int) { (1, 1) } let (a, b) = "
 "get_tuple_of_two_ints(); ~~~~"
@@ -1321,7 +1274,7 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:540
+#: doc/tutorial.md:544
 msgid ""
 "Let bindings only work with _irrefutable_ patterns: that is, patterns that "
 "can never fail to match. This excludes `let` from matching literals and most "
@@ -1333,16 +1286,22 @@ msgstr ""
 "ん。"
 
 #. type: Plain text
-#: doc/tutorial.md:542
+#: doc/tutorial.md:546
 msgid "## Loops"
 msgstr "## ループ"
 
 #. type: Plain text
-#: doc/tutorial.md:547
+#: doc/tutorial.md:551
+#, fuzzy
+#| msgid ""
+#| "`while` denotes a loop that iterates as long as its given condition "
+#| "(which must have type `bool`) evaluates to `true`. Inside a loop, the "
+#| "keyword `break` aborts the loop, and `loop` aborts the current iteration "
+#| "and continues with the next."
 msgid ""
 "`while` denotes a loop that iterates as long as its given condition (which "
 "must have type `bool`) evaluates to `true`. Inside a loop, the keyword "
-"`break` aborts the loop, and `loop` aborts the current iteration and "
+"`break` aborts the loop, and `continue` aborts the current iteration and "
 "continues with the next."
 msgstr ""
 "`while` は、与えられた条件 (`bool` 型の値でなければならない) が `true` と評価"
@@ -1351,19 +1310,7 @@ msgstr ""
 "ション) を中断し、次の繰り返しを実行します。"
 
 #. type: Plain text
-#: doc/tutorial.md:554
-#, no-wrap
-msgid ""
-"~~~~\n"
-"let mut cake_amount = 8;\n"
-"while cake_amount > 0 {\n"
-"    cake_amount -= 1;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:556
+#: doc/tutorial.md:560
 msgid ""
 "`loop` denotes an infinite loop, and is the preferred way of writing `while "
 "true`:"
@@ -1372,39 +1319,24 @@ msgstr ""
 "が推奨されています。"
 
 #. type: Plain text
-#: doc/tutorial.md:566
-#, no-wrap
-msgid ""
-"~~~~\n"
-"use std::int;\n"
-"let mut x = 5;\n"
-"loop {\n"
-"    x += x - 3;\n"
-"    if x % 5 == 0 { break; }\n"
-"    println(int::to_str(x));\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:569
+#: doc/tutorial.md:572
 msgid ""
 "This code prints out a weird sequence of numbers and stops as soon as it "
 "finds one that can be divided by five."
 msgstr "このコードは 5 で割り切れる数値が現れるまで、数値を出力し続けます。"
 
 #. type: Plain text
-#: doc/tutorial.md:571
+#: doc/tutorial.md:574
 msgid "# Data structures"
 msgstr "# データ構造"
 
 #. type: Plain text
-#: doc/tutorial.md:573
+#: doc/tutorial.md:576
 msgid "## Structs"
 msgstr "## 構造体"
 
 #. type: Plain text
-#: doc/tutorial.md:578
+#: doc/tutorial.md:581
 msgid ""
 "Rust struct types must be declared before they are used using the `struct` "
 "syntax: `struct Name { field1: T1, field2: T2 [, ...] }`, where `T1`, "
@@ -1417,7 +1349,7 @@ msgstr ""
 "うに、構造体宣言から `struct` を取り除いたものと同じ構文で作成します。"
 
 #. type: Plain text
-#: doc/tutorial.md:582
+#: doc/tutorial.md:585
 msgid ""
 "Structs are quite similar to C structs and are even laid out the same way in "
 "memory (so you can read from a Rust struct in C, and vice-versa). Use the "
@@ -1428,23 +1360,15 @@ msgstr ""
 "フィールドにアクセスするには、 `mypoint.x` のように、ドット演算子を用います。"
 
 #. type: Plain text
-#: doc/tutorial.md:589
-#, no-wrap
-msgid ""
-"~~~~\n"
-"struct Point {\n"
-"    x: f64,\n"
-"    y: f64\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:593
+#: doc/tutorial.md:595
+#, fuzzy
+#| msgid ""
+#| "Inherited mutability means that any field of a struct may be mutable, if "
+#| "the struct is in a mutable slot (or a field of a struct in a mutable "
+#| "slot, and so forth)."
 msgid ""
-"Inherited mutability means that any field of a struct may be mutable, if the "
-"struct is in a mutable slot (or a field of a struct in a mutable slot, and "
-"so forth)."
+"Structs have \"inherited mutability\", which means that any field of a "
+"struct may be mutable, if the struct is in a mutable slot."
 msgstr ""
 "継承ミュータビリティ (inherited mutability) とは、構造体自体がミュータブルな"
 "スロットに配置されている場合、構造体のすべてのフィールドもミュータブルになる"
@@ -1452,7 +1376,7 @@ msgstr ""
 "フィールドに配置された構造体のフィールドもまた、ミュータブルになります) 。"
 
 #. type: Plain text
-#: doc/tutorial.md:597
+#: doc/tutorial.md:599
 msgid ""
 "With a value (say, `mypoint`) of such a type in a mutable location, you can "
 "do `mypoint.y += 1.0`. But in an immutable location, such an assignment to a "
@@ -1464,10 +1388,10 @@ msgstr ""
 "このような代入操作は型エラーとなります。"
 
 #. type: Plain text
-#: doc/tutorial.md:602
+#: doc/tutorial.md:604
 msgid ""
-"~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = "
-"Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
+"~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point "
+"{ x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
 msgstr ""
 "~~~~ {.xfail-test}\n"
 "# struct Point { x: f64, y: f64 }\n"
@@ -1475,7 +1399,7 @@ msgstr ""
 "let origin = Point { x: 0.0, y: 0.0 };"
 
 #. type: Plain text
-#: doc/tutorial.md:606
+#: doc/tutorial.md:608
 msgid ""
 "mypoint.y += 1.0; // mypoint is mutable, and its fields as well origin.y += "
 "1.0; // ERROR: assigning to immutable field ~~~~"
@@ -1486,7 +1410,7 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:609
+#: doc/tutorial.md:611
 msgid ""
 "`match` patterns destructure structs. The basic syntax is `Name { fieldname: "
 "pattern, ... }`:"
@@ -1495,25 +1419,39 @@ msgstr ""
 "は、 `Name { fieldname: pattern, ... }` という構文を持ちます。"
 
 #. type: Plain text
-#: doc/tutorial.md:618
-#, no-wrap
+#: doc/tutorial.md:620
+#, fuzzy, no-wrap
+#| msgid "~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: 20f }; println(fmt!(\"%f\", point.x)); ~~~"
 msgid ""
 "~~~~\n"
 "# struct Point { x: f64, y: f64 }\n"
 "# let mypoint = Point { x: 0.0, y: 0.0 };\n"
 "match mypoint {\n"
-"    Point { x: 0.0, y: yy } => { println(yy.to_str());                     }\n"
-"    Point { x: xx,  y: yy } => { println(xx.to_str() + \" \" + yy.to_str()); }\n"
+"    Point { x: 0.0, y: yy } => println!(\"{}\", yy),\n"
+"    Point { x: xx,  y: yy } => println!(\"{} {}\", xx, yy),\n"
 "}\n"
 "~~~~\n"
 msgstr ""
+"~~~\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let point = &@~Point { x: 10f, y: 20f };\n"
+"println(fmt!(\"%f\", point.x));\n"
+"~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:625
+#: doc/tutorial.md:627
+#, fuzzy
+#| msgid ""
+#| "In general, the field names of a struct do not have to appear in the same "
+#| "order they appear in the type. When you are not interested in all the "
+#| "fields of a struct, a struct pattern may end with `, _` (as in `Name "
+#| "{ field1, _ }`) to indicate that you're ignoring all other fields.  "
+#| "Additionally, struct fields have a shorthand matching form that simply "
+#| "reuses the field name as the binding name."
 msgid ""
 "In general, the field names of a struct do not have to appear in the same "
 "order they appear in the type. When you are not interested in all the fields "
-"of a struct, a struct pattern may end with `, _` (as in `Name { field1, _ }"
+"of a struct, a struct pattern may end with `, ..` (as in `Name { field1, .. }"
 "`) to indicate that you're ignoring all other fields.  Additionally, struct "
 "fields have a shorthand matching form that simply reuses the field name as "
 "the binding name."
@@ -1524,25 +1462,31 @@ msgstr ""
 "フィールドを無視することができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:633
-#, no-wrap
+#: doc/tutorial.md:635
+#, fuzzy, no-wrap
+#| msgid "~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: 20f }; println(fmt!(\"%f\", point.x)); ~~~"
 msgid ""
 "~~~\n"
 "# struct Point { x: f64, y: f64 }\n"
 "# let mypoint = Point { x: 0.0, y: 0.0 };\n"
 "match mypoint {\n"
-"    Point { x, _ } => { println(x.to_str()) }\n"
+"    Point { x, .. } => println!(\"{}\", x),\n"
 "}\n"
 "~~~\n"
 msgstr ""
+"~~~\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let point = &@~Point { x: 10f, y: 20f };\n"
+"println(fmt!(\"%f\", point.x));\n"
+"~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:635
+#: doc/tutorial.md:637
 msgid "## Enums"
 msgstr "## 列挙型"
 
 #. type: Plain text
-#: doc/tutorial.md:638
+#: doc/tutorial.md:640
 msgid ""
 "Enums are datatypes that have several alternate representations. For "
 "example, consider the type shown earlier:"
@@ -1551,40 +1495,41 @@ msgstr ""
 "いて考えます。"
 
 #. type: Plain text
-#: doc/tutorial.md:646
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# struct Point { x: f64, y: f64 }\n"
-"enum Shape {\n"
-"    Circle(Point, f64),\n"
-"    Rectangle(Point, Point)\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:652
+#: doc/tutorial.md:654
+#, fuzzy
+#| msgid ""
+#| "A value of this type is either a `Circle`, in which case it contains a "
+#| "`Point` struct and a `f64`, or a `Rectangle`, in which case it contains "
+#| "two `Point` structs. The run-time representation of such a value includes "
+#| "an identifier of the actual form that it holds, much like the \"tagged "
+#| "union\" pattern in C, but with better static guarantees."
 msgid ""
 "A value of this type is either a `Circle`, in which case it contains a "
-"`Point` struct and a `f64`, or a `Rectangle`, in which case it contains two "
+"`Point` struct and a f64, or a `Rectangle`, in which case it contains two "
 "`Point` structs. The run-time representation of such a value includes an "
 "identifier of the actual form that it holds, much like the \"tagged union\" "
 "pattern in C, but with better static guarantees."
 msgstr ""
-"この型の値は、`Point` 構造体と `f64` を含む `Circle` か、2つの `Point` 構造"
-"体を含む `Rectangle` のどちらかになります。列挙型の値の実行時表現には、値がど"
-"の形式をとっているのか示す識別子が含まれます。この表現方法は C の \"タグ付き"
-"共用体\" と非常によく似ていますが、Rust の列挙型はコンパイラにより値の正当性"
-"静的に保証されるという点でより良いものとなっています。"
+"この型の値は、`Point` 構造体と `f64` を含む `Circle` か、2つの `Point` 構造"
+"を含む `Rectangle` のどちらかになります。列挙型の値の実行時表現には、値がどの"
+"形式をとっているのか示す識別子が含まれます。この表現方法は C の \"タグ付き共"
+"用体\" と非常によく似ていますが、Rust の列挙型はコンパイラにより値の正当性が"
+"静的に保証されるという点でより良いものとなっています。"
 
 #. type: Plain text
-#: doc/tutorial.md:658
+#: doc/tutorial.md:660
+#, fuzzy
+#| msgid ""
+#| "The above declaration will define a type `Shape` that can refer to such "
+#| "shapes, and two functions, `Circle` and `Rectangle`, which can be used to "
+#| "construct values of the type (taking arguments of the specified types). "
+#| "So `Circle(Point { x: 0f, y: 0f }, 10f)` is the way to create a new "
+#| "circle."
 msgid ""
 "The above declaration will define a type `Shape` that can refer to such "
 "shapes, and two functions, `Circle` and `Rectangle`, which can be used to "
 "construct values of the type (taking arguments of the specified types). So "
-"`Circle(Point { x: 0f, y: 0f }, 10f)` is the way to create a new circle."
+"`Circle(Point { x: 0.0, y: 0.0 }, 10.0)` is the way to create a new circle."
 msgstr ""
 "上記の宣言は `Shape` 型と `Circle` と `Rectangle` という2つの関数も同時に定義"
 "します。これらの関数により、関数名に対応した `Shape` 型の値を構築することがで"
@@ -1593,7 +1538,7 @@ msgstr ""
 "ことができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:661
+#: doc/tutorial.md:663
 msgid ""
 "Enum variants need not have parameters. This `enum` declaration, for "
 "example, is equivalent to a C enum:"
@@ -1602,21 +1547,7 @@ msgstr ""
 "言は C の列挙型と等価です。"
 
 #. type: Plain text
-#: doc/tutorial.md:670
-#, no-wrap
-msgid ""
-"~~~~\n"
-"enum Direction {\n"
-"    North,\n"
-"    East,\n"
-"    South,\n"
-"    West\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:673
+#: doc/tutorial.md:675
 msgid ""
 "This declaration defines `North`, `East`, `South`, and `West` as constants, "
 "all of which have type `Direction`."
@@ -1625,7 +1556,7 @@ msgstr ""
 "す。"
 
 #. type: Plain text
-#: doc/tutorial.md:677
+#: doc/tutorial.md:679
 msgid ""
 "When an enum is C-like (that is, when none of the variants have parameters), "
 "it is possible to explicitly set the discriminator values to a constant "
@@ -1635,20 +1566,7 @@ msgstr ""
 "識別値 (discriminator value) を明示的に指定することも可能です。"
 
 #. type: Plain text
-#: doc/tutorial.md:685
-#, no-wrap
-msgid ""
-"~~~~\n"
-"enum Color {\n"
-"  Red = 0xff0000,\n"
-"  Green = 0x00ff00,\n"
-"  Blue = 0x0000ff\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:690
+#: doc/tutorial.md:692
 msgid ""
 "If an explicit discriminator is not specified for a variant, the value "
 "defaults to the value of the previous variant plus one. If the first variant "
@@ -1660,7 +1578,7 @@ msgstr ""
 "で言うと、 `North` は 0、 `East` は 1、 `South` は 2、`West` は3となります。"
 
 #. type: Plain text
-#: doc/tutorial.md:693
+#: doc/tutorial.md:695
 msgid ""
 "When an enum is C-like, you can apply the `as` cast operator to convert it "
 "to its discriminator value as an `int`."
@@ -1669,7 +1587,7 @@ msgstr ""
 "値へ変換することができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:697
+#: doc/tutorial.md:699
 msgid ""
 "For enum types with multiple variants, destructuring is the only way to get "
 "at their contents. All variant constructors can be used as patterns, as in "
@@ -1680,27 +1598,15 @@ msgstr ""
 "トのコンストラクタは、パターンとして用いることもできます。"
 
 #. type: Plain text
-#: doc/tutorial.md:709
-#, no-wrap
-msgid ""
-"~~~~\n"
-"use std::f64;\n"
-"# struct Point {x: f64, y: f64}\n"
-"# enum Shape { Circle(Point, f64), Rectangle(Point, Point) }\n"
-"fn area(sh: Shape) -> f64 {\n"
-"    match sh {\n"
-"        Circle(_, size) => f64::consts::pi * size * size,\n"
-"        Rectangle(Point { x, y }, Point { x: x2, y: y2 }) => (x2 - x) * (y2 - y)\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:714
+#: doc/tutorial.md:716
+#, fuzzy
+#| msgid ""
+#| "You can write a lone `_` to ignore an individual field, and can ignore "
+#| "all fields of a variant like: `Circle(*)`. As in their introduction form, "
+#| "nullary enum patterns are written without parentheses."
 msgid ""
 "You can write a lone `_` to ignore an individual field, and can ignore all "
-"fields of a variant like: `Circle(*)`. As in their introduction form, "
+"fields of a variant like: `Circle(..)`. As in their introduction form, "
 "nullary enum patterns are written without parentheses."
 msgstr ""
 "パターンマッチの際に、特定のフィールドに対するマッチングが不要な場合、無視し"
@@ -1710,63 +1616,28 @@ msgstr ""
 "い形式で記述します。"
 
 #. type: Plain text
-#: doc/tutorial.md:727
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# struct Point { x: f64, y: f64 }\n"
-"# enum Direction { North, East, South, West }\n"
-"fn point_from_direction(dir: Direction) -> Point {\n"
-"    match dir {\n"
-"        North => Point { x:  0f, y:  1f },\n"
-"        East  => Point { x:  1f, y:  0f },\n"
-"        South => Point { x:  0f, y: -1f },\n"
-"        West  => Point { x: -1f, y:  0f }\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:729
+#: doc/tutorial.md:731
 msgid "Enum variants may also be structs. For example:"
 msgstr "以下の例のように、列挙型バリアントを構造体にすることも可能です。"
 
 #. type: Plain text
-#: doc/tutorial.md:747
-#, no-wrap
-msgid ""
-"~~~~\n"
-"use std::f64;\n"
-"# struct Point { x: f64, y: f64 }\n"
-"# fn square(x: f64) -> f64 { x * x }\n"
-"enum Shape {\n"
-"    Circle { center: Point, radius: f64 },\n"
-"    Rectangle { top_left: Point, bottom_right: Point }\n"
-"}\n"
-"fn area(sh: Shape) -> f64 {\n"
-"    match sh {\n"
-"        Circle { radius: radius, _ } => f64::consts::pi * square(radius),\n"
-"        Rectangle { top_left: top_left, bottom_right: bottom_right } => {\n"
-"            (bottom_right.x - top_left.x) * (bottom_right.y - top_left.y)\n"
-"        }\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:749
+#: doc/tutorial.md:755
 msgid "## Tuples"
 msgstr "## タプル"
 
 #. type: Plain text
-#: doc/tutorial.md:754
+#: doc/tutorial.md:760
+#, fuzzy
+#| msgid ""
+#| "Tuples in Rust behave exactly like structs, except that their fields do "
+#| "not have names. Thus, you cannot access their fields with dot notation.  "
+#| "Tuples can have any arity except for 0 (though you may consider unit, "
+#| "`()`, as the empty tuple if you like)."
 msgid ""
 "Tuples in Rust behave exactly like structs, except that their fields do not "
 "have names. Thus, you cannot access their fields with dot notation.  Tuples "
-"can have any arity except for 0 (though you may consider unit, `()`, as the "
-"empty tuple if you like)."
+"can have any arity (number of elements) except for 0 (though you may "
+"consider unit, `()`, as the empty tuple if you like)."
 msgstr ""
 "Rust のタプルは、フィールドが名前を持たないという点以外は、構造体と同じように"
 "振る舞います。フィールド名が存在しないため、ドット記法を使ってタプルのフィー"
@@ -1774,24 +1645,40 @@ msgstr ""
 "す (必要ならば、ユニット型 `()` を 0 要素のタプルと見なすことはできます。)"
 
 #. type: Plain text
-#: doc/tutorial.md:761
-#, no-wrap
+#: doc/tutorial.md:767
+#, fuzzy, no-wrap
+#| msgid ""
+#| "For example:\n"
+#| "~~~~\n"
+#| "struct MyTup(int, int, f64);\n"
+#| "let mytup: MyTup = MyTup(10, 20, 30.0);\n"
+#| "match mytup {\n"
+#| "  MyTup(a, b, c) => info!(a + b + (c as int))\n"
+#| "}\n"
+#| "~~~~\n"
 msgid ""
 "~~~~\n"
 "let mytup: (int, int, f64) = (10, 20, 30.0);\n"
 "match mytup {\n"
-"  (a, b, c) => info!(a + b + (c as int))\n"
+"  (a, b, c) => info!(\"{}\", a + b + (c as int))\n"
 "}\n"
 "~~~~\n"
 msgstr ""
+"~~~~\n"
+"struct MyTup(int, int, f64);\n"
+"let mytup: MyTup = MyTup(10, 20, 30.0);\n"
+"match mytup {\n"
+"  MyTup(a, b, c) => info!(a + b + (c as int))\n"
+"}\n"
+"~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:763
+#: doc/tutorial.md:769
 msgid "## Tuple structs"
 msgstr "## タプル構造体"
 
 #. type: Plain text
-#: doc/tutorial.md:768
+#: doc/tutorial.md:774
 msgid ""
 "Rust also has _tuple structs_, which behave like both structs and tuples, "
 "except that, unlike tuples, tuple structs have names (so `Foo(1, 2)` has a "
@@ -1804,15 +1691,23 @@ msgstr ""
 "フィールド__ は名前を持ちません。"
 
 #. type: Plain text
-#: doc/tutorial.md:777
-#, no-wrap
+#: doc/tutorial.md:784
+#, fuzzy, no-wrap
+#| msgid ""
+#| "For example:\n"
+#| "~~~~\n"
+#| "struct MyTup(int, int, f64);\n"
+#| "let mytup: MyTup = MyTup(10, 20, 30.0);\n"
+#| "match mytup {\n"
+#| "  MyTup(a, b, c) => info!(a + b + (c as int))\n"
+#| "}\n"
+#| "~~~~\n"
 msgid ""
-"For example:\n"
 "~~~~\n"
 "struct MyTup(int, int, f64);\n"
 "let mytup: MyTup = MyTup(10, 20, 30.0);\n"
 "match mytup {\n"
-"  MyTup(a, b, c) => info!(a + b + (c as int))\n"
+"  MyTup(a, b, c) => info!(\"{}\", a + b + (c as int))\n"
 "}\n"
 "~~~~\n"
 msgstr ""
@@ -1825,12 +1720,7 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:779
-msgid "<a name=\"newtype\"></a>"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:784
+#: doc/tutorial.md:791
 msgid ""
 "There is a special case for tuple structs with a single field, which are "
 "sometimes called \"newtypes\" (after Haskell's \"newtype\" feature). These "
@@ -1843,7 +1733,7 @@ msgstr ""
 "きます。この新しい型は、元にした型とは異なった型として扱われます。"
 
 #. type: Plain text
-#: doc/tutorial.md:788
+#: doc/tutorial.md:795
 msgid "~~~~ struct GizmoId(int); ~~~~"
 msgstr ""
 "~~~~\n"
@@ -1851,37 +1741,20 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:791
-msgid ""
-"For convenience, you can extract the contents of such a struct with the "
-"dereference (`*`) unary operator:"
-msgstr ""
-"便宜上、デリファレンス単項演算子 (`*`) により、タプル構造体の内容を展開するこ"
-"とが可能です。"
-
-#. type: Plain text
-#: doc/tutorial.md:797
-msgid ""
-"~~~~ # struct GizmoId(int); let my_gizmo_id: GizmoId = GizmoId(10); let "
-"id_int: int = *my_gizmo_id; ~~~~"
-msgstr ""
-"~~~~\n"
-"# struct GizmoId(int);\n"
-"let my_gizmo_id: GizmoId = GizmoId(10);\n"
-"let id_int: int = *my_gizmo_id;\n"
-"~~~~"
-
-#. type: Plain text
-#: doc/tutorial.md:800
+#: doc/tutorial.md:798
+#, fuzzy
+#| msgid ""
+#| "Types like this can be useful to differentiate between data that have the "
+#| "same type but must be used in different ways."
 msgid ""
 "Types like this can be useful to differentiate between data that have the "
-"same type but must be used in different ways."
+"same underlying type but must be used in different ways."
 msgstr ""
 "このような型は、型は同一でも、それぞれ全く異なる扱い方をしなければならない"
 "データを扱う場合に用いると便利です。"
 
 #. type: Plain text
-#: doc/tutorial.md:805
+#: doc/tutorial.md:803
 msgid "~~~~ struct Inches(int); struct Centimeters(int); ~~~~"
 msgstr ""
 "~~~~\n"
@@ -1890,37 +1763,62 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:808
+#: doc/tutorial.md:807
+#, fuzzy
+#| msgid ""
+#| "The above definitions allow for a simple way for programs to avoid "
+#| "confusing numbers that correspond to different units."
 msgid ""
 "The above definitions allow for a simple way for programs to avoid confusing "
-"numbers that correspond to different units."
+"numbers that correspond to different units. Their integer values can be "
+"extracted with pattern matching:"
 msgstr ""
 "上記のような単純な定義により、異なる単位を持つ数値を混同することなく扱うこと"
 "が可能になります。"
 
 #. type: Plain text
 #: doc/tutorial.md:810
+#, fuzzy
+#| msgid "~~~~ struct GizmoId(int); ~~~~"
+msgid "~~~ # struct Inches(int);"
+msgstr ""
+"~~~~\n"
+"struct GizmoId(int);\n"
+"~~~~"
+
+#. type: Plain text
+#: doc/tutorial.md:817
 msgid "# Functions"
 msgstr "# 関数"
 
 #. type: Plain text
-#: doc/tutorial.md:818
+#: doc/tutorial.md:825
+#, fuzzy
+#| msgid ""
+#| "We've already seen several function definitions. Like all other static "
+#| "declarations, such as `type`, functions can be declared both at the top "
+#| "level and inside other functions (or in modules, which we'll come back to "
+#| "[later](#modules-and-crates)). The `fn` keyword introduces a function. A "
+#| "function has an argument list, which is a parenthesized list of `expr: "
+#| "type` pairs separated by commas. An arrow `->` separates the argument "
+#| "list and the function's return type."
 msgid ""
 "We've already seen several function definitions. Like all other static "
 "declarations, such as `type`, functions can be declared both at the top "
 "level and inside other functions (or in modules, which we'll come back to "
-"[later](#modules-and-crates)). The `fn` keyword introduces a function. A "
-"function has an argument list, which is a parenthesized list of `expr: type` "
-"pairs separated by commas. An arrow `->` separates the argument list and the "
-"function's return type."
+"[later](#crates-and-the-module-system)). The `fn` keyword introduces a "
+"function. A function has an argument list, which is a parenthesized list of "
+"`name: type` pairs separated by commas. An arrow `->` separates the argument "
+"list and the function's return type."
 msgstr ""
 "関数定義はこれまでに何度か登場しています。他の静的な宣言 (`type` など)と同様"
 "に、関数はトップレベルまたは、他の関数の内部、モジュールの内部で定義すること"
 "ができます (モジュールについては、[後述](#モジュールとクレート)します) 。"
 
 #. type: Plain text
-#: doc/tutorial.md:824
-#, no-wrap
+#: doc/tutorial.md:831
+#, fuzzy, no-wrap
+#| msgid "~~~~ fn line(a: int, b: int, x: int) -> int { a * x + b } fn oops(a: int, b: int, x: int) -> ()  { a * x + b; }"
 msgid ""
 "~~~~\n"
 "fn line(a: int, b: int, x: int) -> int {\n"
@@ -1928,9 +1826,12 @@ msgid ""
 "}\n"
 "~~~~\n"
 msgstr ""
+"~~~~\n"
+"fn line(a: int, b: int, x: int) -> int { a * x + b }\n"
+"fn oops(a: int, b: int, x: int) -> ()  { a * x + b; }"
 
 #. type: Plain text
-#: doc/tutorial.md:829
+#: doc/tutorial.md:836
 msgid ""
 "The `return` keyword immediately returns from the body of a function. It is "
 "optionally followed by an expression to return. A function can also return a "
@@ -1942,8 +1843,9 @@ msgstr ""
 "値) も関数の戻り値になります。"
 
 #. type: Plain text
-#: doc/tutorial.md:835
-#, no-wrap
+#: doc/tutorial.md:842
+#, fuzzy, no-wrap
+#| msgid "~~~~ fn line(a: int, b: int, x: int) -> int { a * x + b } fn oops(a: int, b: int, x: int) -> ()  { a * x + b; }"
 msgid ""
 "~~~~\n"
 "fn line(a: int, b: int, x: int) -> int {\n"
@@ -1951,9 +1853,12 @@ msgid ""
 "}\n"
 "~~~~\n"
 msgstr ""
+"~~~~\n"
+"fn line(a: int, b: int, x: int) -> int { a * x + b }\n"
+"fn oops(a: int, b: int, x: int) -> ()  { a * x + b; }"
 
 #. type: Plain text
-#: doc/tutorial.md:842
+#: doc/tutorial.md:849
 msgid ""
 "It's better Rust style to write a return value this way instead of writing "
 "an explicit `return`. The utility of `return` comes in when returning early "
@@ -1967,27 +1872,27 @@ msgstr ""
 "の型や、戻り値を返す処理を省略することが可能です。以下の2つの関数は等価です。"
 
 #. type: Plain text
-#: doc/tutorial.md:845
+#: doc/tutorial.md:852
 msgid "~~~~ fn do_nothing_the_hard_way() -> () { return (); }"
 msgstr ""
 "~~~~\n"
 "fn do_nothing_the_hard_way() -> () { return (); }"
 
 #. type: Plain text
-#: doc/tutorial.md:848
+#: doc/tutorial.md:855
 msgid "fn do_nothing_the_easy_way() { } ~~~~"
 msgstr ""
 "fn do_nothing_the_easy_way() { }\n"
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:850
+#: doc/tutorial.md:857
 msgid ""
 "Ending the function with a semicolon like so is equivalent to returning `()`."
 msgstr "以下のように、セミコロンで終わる関数は `()` を返す関数と等価です。"
 
 #. type: Plain text
-#: doc/tutorial.md:854
+#: doc/tutorial.md:861
 msgid ""
 "~~~~ fn line(a: int, b: int, x: int) -> int { a * x + b } fn oops(a: int, b: "
 "int, x: int) -> ()  { a * x + b; }"
@@ -1997,7 +1902,7 @@ msgstr ""
 "fn oops(a: int, b: int, x: int) -> ()  { a * x + b; }"
 
 #. type: Plain text
-#: doc/tutorial.md:858
+#: doc/tutorial.md:865
 msgid "assert!(8 == line(5, 3, 1)); assert!(() == oops(5, 3, 1)); ~~~~"
 msgstr ""
 "assert!(8 == line(5, 3, 1));\n"
@@ -2005,7 +1910,7 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:862
+#: doc/tutorial.md:869
 msgid ""
 "As with `match` expressions and `let` bindings, function arguments support "
 "pattern destructuring. Like `let`, argument patterns must be irrefutable, as "
@@ -2017,7 +1922,7 @@ msgstr ""
 "し、呼び出し元へ返します。"
 
 #. type: Plain text
-#: doc/tutorial.md:866
+#: doc/tutorial.md:873
 msgid "~~~ fn first((value, _): (int, f64)) -> int { value } ~~~"
 msgstr ""
 "~~~\n"
@@ -2025,12 +1930,7 @@ msgstr ""
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:868 doc/tutorial-ffi.md:143
-msgid "# Destructors"
-msgstr "# デストラクタ"
-
-#. type: Plain text
-#: doc/tutorial.md:872
+#: doc/tutorial.md:879
 msgid ""
 "A *destructor* is a function responsible for cleaning up the resources used "
 "by an object when it is no longer accessible. Destructors can be defined to "
@@ -2041,11 +1941,16 @@ msgstr ""
 "リのようなリソースの解放を処理するために定義することができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:876
+#: doc/tutorial.md:883
+#, fuzzy
+#| msgid ""
+#| "Objects are never accessible after their destructor has been called, so "
+#| "there are no dynamic failures from accessing freed resources. When a task "
+#| "fails, the destructors of all objects in the task are called."
 msgid ""
-"Objects are never accessible after their destructor has been called, so "
-"there are no dynamic failures from accessing freed resources. When a task "
-"fails, the destructors of all objects in the task are called."
+"Objects are never accessible after their destructor has been called, so no "
+"dynamic failures are possible from accessing freed resources. When a task "
+"fails, destructors of all objects in the task are called."
 msgstr ""
 "オブジェクトは、デストラクタが呼び出された後にアクセス不能になります。そのた"
 "め、解放済みリソースへアクセスしたことによる動的なエラーは発生しません。タス"
@@ -2053,7 +1958,7 @@ msgstr ""
 "び出されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:878
+#: doc/tutorial.md:885
 msgid ""
 "The `~` sigil represents a unique handle for a memory allocation on the heap:"
 msgstr ""
@@ -2061,20 +1966,7 @@ msgstr ""
 "す。"
 
 #. type: Plain text
-#: doc/tutorial.md:886
-#, no-wrap
-msgid ""
-"~~~~\n"
-"{\n"
-"    // an integer allocated on the heap\n"
-"    let y = ~10;\n"
-"}\n"
-"// the destructor frees the heap memory as soon as `y` goes out of scope\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:890
+#: doc/tutorial.md:897
 msgid ""
 "Rust includes syntax for heap memory allocation in the language since it's "
 "commonly used, but the same semantics can be implemented by a type with a "
@@ -2085,12 +1977,12 @@ msgstr ""
 "り実装することが可能です。"
 
 #. type: Plain text
-#: doc/tutorial.md:892
+#: doc/tutorial.md:899
 msgid "# Ownership"
 msgstr "# 所有権"
 
 #. type: Plain text
-#: doc/tutorial.md:897
+#: doc/tutorial.md:904
 msgid ""
 "Rust formalizes the concept of object ownership to delegate management of an "
 "object's lifetime to either a variable or a task-local garbage collector. An "
@@ -2105,13 +1997,18 @@ msgstr ""
 "断します。"
 
 #. type: Plain text
-#: doc/tutorial.md:903
+#: doc/tutorial.md:908
+#, fuzzy
+#| msgid ""
+#| "Ownership is recursive, so mutability is inherited recursively and a "
+#| "destructor destroys the contained tree of owned objects. Variables are "
+#| "top-level owners and destroy the contained object when they go out of "
+#| "scope. A box managed by the garbage collector starts a new ownership "
+#| "tree, and the destructor is called when it is collected."
 msgid ""
 "Ownership is recursive, so mutability is inherited recursively and a "
 "destructor destroys the contained tree of owned objects. Variables are top-"
-"level owners and destroy the contained object when they go out of scope. A "
-"box managed by the garbage collector starts a new ownership tree, and the "
-"destructor is called when it is collected."
+"level owners and destroy the contained object when they go out of scope."
 msgstr ""
 "所有権は再帰的であるため、ミュータビリティは再帰的に継承され、デストラクタは"
 "所有しているオブジェクトの含まれているツリーを破壊します。変数はトップレベル"
@@ -2121,7 +2018,7 @@ msgstr ""
 "きにデストラクタが呼び出されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:907
+#: doc/tutorial.md:912
 msgid ""
 "~~~~ // the struct owns the objects contained in the `x` and `y` fields "
 "struct Foo { x: int, y: ~int }"
@@ -2131,7 +2028,7 @@ msgstr ""
 "struct Foo { x: int, y: ~int }"
 
 #. type: Plain text
-#: doc/tutorial.md:914
+#: doc/tutorial.md:919
 #, no-wrap
 msgid ""
 "{\n"
@@ -2148,7 +2045,7 @@ msgstr ""
 "// `a` の含まれているスコープから抜けるとき、 構造体のフィールドの `~int` のデストラクタが呼ばれる\n"
 
 #. type: Plain text
-#: doc/tutorial.md:919
+#: doc/tutorial.md:924
 msgid ""
 "// `b` is mutable, and the mutability is inherited by the objects it owns "
 "let mut b = Foo { x: 5, y: ~10 }; b.x = 10; ~~~~"
@@ -2160,13 +2057,21 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:925
+#: doc/tutorial.md:931
+#, fuzzy
+#| msgid ""
+#| "If an object doesn't contain garbage-collected boxes, it consists of a "
+#| "single ownership tree and is given the `Owned` trait which allows it to "
+#| "be sent between tasks. Custom destructors can only be implemented "
+#| "directly on types that are `Owned`, but garbage-collected boxes can still "
+#| "*contain* types with custom destructors."
 msgid ""
-"If an object doesn't contain garbage-collected boxes, it consists of a "
-"single ownership tree and is given the `Owned` trait which allows it to be "
+"If an object doesn't contain any non-Send types, it consists of a single "
+"ownership tree and is itself given the `Send` trait which allows it to be "
 "sent between tasks. Custom destructors can only be implemented directly on "
-"types that are `Owned`, but garbage-collected boxes can still *contain* "
-"types with custom destructors."
+"types that are `Send`, but non-`Send` types can still *contain* types with "
+"custom destructors. Example of types which are not `Send` are [`Gc<T>`][gc] "
+"and [`Rc<T>`][rc], the shared-ownership types."
 msgstr ""
 "オブジェクトにガベージコレクトされるボックスが含まれていない場合、オブジェク"
 "トは単一の継承ツリーからの構成され、`Owned` トレイトが付与されます。`Owned` "
@@ -2175,282 +2080,35 @@ msgstr ""
 "せんが、ガベージコレクトされるボックスが独自のデストラクタをもつ型を **含む"
 "** ことは依然可能です。"
 
-#. type: Plain text
-#: doc/tutorial.md:927
-msgid "# Boxes"
-msgstr "# ボックス"
-
 #. type: Plain text
 #: doc/tutorial.md:934
+#, fuzzy
+#| msgid ""
+#| "[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz [win-exe]: "
+#| "http://static.rust-lang.org/dist/rust-0.7-install.exe"
 msgid ""
-"Many modern languages represent values as pointers to heap memory by "
-"default. In contrast, Rust, like C and C++, represents such types directly.  "
-"Another way to say this is that aggregate data in Rust are *unboxed*. This "
-"means that if you `let x = Point { x: 1f, y: 1f };`, you are creating a "
-"struct on the stack. If you then copy it into a data structure, you copy the "
-"entire struct, not just a pointer."
-msgstr ""
-"多くのモダンな言語では、デフォルトで、値はヒープメモリへのポインタとして表さ"
-"れます。一方、Rust は C や C++ のように、これらの型を直接取り扱うことができま"
-"す。言い換えると、集積データは **ボックス化されていない** ということです。つ"
-"まり、`let x = Point { x: 1f, y: 1f };` というコードは、スタック上に構造体を"
-"作成することを意味します。この構造体を別のデータ構造の中へコピーする場合、ポ"
-"インタのコピーではなく構造体全体をコピーすることになります。"
-
-#. type: Plain text
-#: doc/tutorial.md:939
-msgid ""
-"For small structs like `Point`, this is usually more efficient than "
-"allocating memory and indirecting through a pointer. But for big structs, or "
-"mutable state, it can be useful to have a single copy on the stack or on the "
-"heap, and refer to that through a pointer."
-msgstr ""
-"`Point` のような小さな構造体の場合、このような動作は、メモリを獲得しポインタ"
-"経由でアクセスするよりも一般的には効率的です。しかし、大きな構造体の場合や"
-"ミュータブルな状態を持つようなものの場合、スタックまたはヒープ上に単一ののコ"
-"ピーをもち、ポインタ経由で参照する方が便利な場合もあります。"
-
-#. type: Plain text
-#: doc/tutorial.md:941
-msgid "## Owned boxes"
-msgstr "## 所有ボックス"
-
-#. type: Plain text
-#: doc/tutorial.md:944
-msgid ""
-"An owned box (`~`) is a uniquely owned allocation on the heap. It inherits "
-"the mutability and lifetime of the owner as it would if there was no box:"
-msgstr ""
-"所有ボックス (Owned box, `~`) は、単一の所有者のみを持つ、ヒープ上に獲得され"
-"た領域です。所有ボックスは、ボックスが存在しない場合と同じように、所有者の"
-"ミュータビリティと寿命を継承します。"
-
-#. type: Plain text
-#: doc/tutorial.md:949
-msgid "~~~~ let x = 5; // immutable let mut y = 5; // mutable y += 2;"
-msgstr ""
-"~~~~\n"
-"let x = 5; // イミュータブル\n"
-"let mut y = 5; // ミュータブル\n"
-"y += 2;"
-
-#. type: Plain text
-#: doc/tutorial.md:954
-msgid ""
-"let x = ~5; // immutable let mut y = ~5; // mutable *y += 2; // the * "
-"operator is needed to access the contained value ~~~~"
-msgstr ""
-"let x = ~5; // イミュータブル\n"
-"let mut y = ~5; // ミュータブル\n"
-"*y += 2; // ボックスの中身にアクセスするには、 * 演算子が必要\n"
-"~~~~"
-
-#. type: Plain text
-#: doc/tutorial.md:959
-msgid ""
-"The purpose of an owned box is to add a layer of indirection in order to "
-"create recursive data structures or cheaply pass around an object larger "
-"than a pointer. Since an owned box has a unique owner, it can only be used "
-"to represent a tree data structure."
-msgstr ""
-"所有ボックスの目的は、再帰的なデータ型の作成や、ポインターのサイズより大きい"
-"オブジェクトを安価な方法で渡したりするための、関節参照のレイヤを追加すること"
-"です。所有ボックスは複数の所有者を持てないため、ツリー構造を持ったデータのみ"
-"を表すことが可能です。"
-
-#. type: Plain text
-#: doc/tutorial.md:962
-msgid ""
-"The following struct won't compile, because the lack of indirection would "
-"mean it has an infinite size:"
-msgstr ""
-"以下の構造体はコンパイルできません。構造体が自身を関節参照でない方法で参照し"
-"た場合、無限に大きなサイズを持つことになってしまうからです。"
-
-#. type: Plain text
-#: doc/tutorial.md:968
-#, no-wrap
-msgid ""
-"~~~~ {.xfail-test}\n"
-"struct Foo {\n"
-"    child: Option<Foo>\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:972
-msgid ""
-"> ***Note:*** The `Option` type is an enum that represents an *optional* "
-"value.  > It's comparable to a nullable pointer in many other languages, but "
-"stores the > contained value unboxed."
-msgstr ""
-"> ***注意*** `Option` 型は **オプショナルな** (値の有無を選択可能な) 値を表す"
-"列挙型です。`Option` 型は他の言語の null 値をとりうるポインタ型に相当します"
-"が、格納される値はボックス化されていません。"
-
-#. type: Plain text
-#: doc/tutorial.md:976
-msgid ""
-"Adding indirection with an owned pointer allocates the child outside of the "
-"struct on the heap, which makes it a finite size and won't result in a "
-"compile-time error:"
-msgstr ""
-"所有ポインタによる関節参照を導入することで、`child` を構造体の外のヒープ上に"
-"獲得することができ、構造体のデータサイズは有限となるため、コンパイルエラーと"
-"はなりません。"
-
-#. type: Plain text
-#: doc/tutorial.md:982
-#, no-wrap
-msgid ""
-"~~~~\n"
-"struct Foo {\n"
-"    child: Option<~Foo>\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:984
-msgid "## Managed boxes"
-msgstr "## マネージドボックス"
-
-#. type: Plain text
-#: doc/tutorial.md:992
-msgid ""
-"A managed box (`@`) is a heap allocation with the lifetime managed by a task-"
-"local garbage collector. It will be destroyed at some point after there are "
-"no references left to the box, no later than the end of the task. Managed "
-"boxes lack an owner, so they start a new ownership tree and don't inherit "
-"mutability. They do own the contained object, and mutability is defined by "
-"the type of the managed box (`@` or `@mut`). An object containing a managed "
-"box is not `Owned`, and can't be sent between tasks."
-msgstr ""
-"マネージドボックス (`@`) は、タスクローカルなガベージコレクタにより寿命管理さ"
-"れる、ヒープ上に獲得された領域です。マネージドボックスは、ボックスへの参照が"
-"無くなった後、いずれかの時点で破棄されます。破棄のタイミングがタスク終了後に"
-"なることはありません。マネージドボックスは所有者を持たないので、新たな所有権"
-"ツリーを開始し、ミュータビリティを継承しません。マネージドボックスは、ボック"
-"スに含まれているオブジェクトを所有し、ミュータビリティはマネージドボックスの"
-"種別 (`@` または `@mut`) によって決定されます。マネージドボックスに含まれるオ"
-"ブジェクトは `Owned` を付与されず、タスク間で受け渡すことはできません。"
-
-#. type: Plain text
-#: doc/tutorial.md:995
-msgid "~~~~ let a = @5; // immutable"
-msgstr ""
-"~~~~\n"
-"let a = @5; // イミュータブル"
-
-#. type: Plain text
-#: doc/tutorial.md:998
-msgid "let mut b = @5; // mutable variable, immutable box b = @10;"
-msgstr ""
-"let mut b = @5; // ミュータブルな変数、イミュータブルなボックス\n"
-"b = @10;"
-
-#. type: Plain text
-#: doc/tutorial.md:1001
-msgid "let c = @mut 5; // immutable variable, mutable box *c = 10;"
-msgstr ""
-"let c = @mut 5; // イミュータブルな変数、ミュータブルなボックス\n"
-"*c = 10;"
-
-#. type: Plain text
-#: doc/tutorial.md:1006
-msgid ""
-"let mut d = @mut 5; // mutable variable, mutable box *d += 5; d = @mut 15; "
-"~~~~"
-msgstr ""
-"let mut d = @mut 5; // ミュータブルな変数、ミュータブルなボックス\n"
-"*d += 5;\n"
-"d = @mut 15;\n"
-"~~~~"
-
-#. type: Plain text
-#: doc/tutorial.md:1011
-msgid ""
-"A mutable variable and an immutable variable can refer to the same box, "
-"given that their types are compatible. Mutability of a box is a property of "
-"its type, however, so for example a mutable handle to an immutable box "
-"cannot be assigned a reference to a mutable box."
+"[gc]: http://static.rust-lang.org/doc/master/std/gc/struct.Gc.html [rc]: "
+"http://static.rust-lang.org/doc/master/std/rc/struct.Rc.html"
 msgstr ""
-"ミュータブルな変数とイミュータブルな変数は、それぞれの変数の型が同じであれ"
-"ば、同じボックスを参照することが可能です。ただし、ボックスのミュータビリティ"
-"は、型自体が持つ属性なので、ミュータブルなボックスの参照を、イミュータブルな"
-"ボックスを参照するミュータブルな変数 (handle) へ代入することはできません。"
-
-#. type: Plain text
-#: doc/tutorial.md:1015
-#, no-wrap
-msgid ""
-"~~~~\n"
-"let a = @1;     // immutable box\n"
-"let b = @mut 2; // mutable box\n"
-msgstr ""
-"~~~~\n"
-"let a = @1;     // イミュータブルなボックス\n"
-"let b = @mut 2; // ミュータブルなボックス\n"
-
-#. type: Plain text
-#: doc/tutorial.md:1018
-#, no-wrap
-msgid ""
-"let mut c : @int;       // declare a variable with type managed immutable int\n"
-"let mut d : @mut int;   // and one of type managed mutable int\n"
-msgstr ""
-"let mut c : @int;       // イミュータブルなマネージド int 型の変数と、\n"
-"let mut d : @mut int;   // ミュータブルなマネージド int 型の変数の宣言\n"
-
-#. type: Plain text
-#: doc/tutorial.md:1022
-#, no-wrap
-msgid ""
-"c = a;          // box type is the same, okay\n"
-"d = b;          // box type is the same, okay\n"
-"~~~~\n"
-msgstr ""
-"c = a;          // ボックスの型は変数の型と同じなので、OK\n"
-"d = b;          // ボックスの型は変数の型と同じなので、OK\n"
-"~~~~\n"
+"[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz\n"
+"[win-exe]: http://static.rust-lang.org/dist/rust-0.7-install.exe"
 
 #. type: Plain text
-#: doc/tutorial.md:1027
-#, no-wrap
-msgid ""
-"~~~~ {.xfail-test}\n"
-"// but b cannot be assigned to c, or a to d\n"
-"c = b;          // error\n"
-"~~~~\n"
-msgstr ""
-"~~~~ {.xfail-test}\n"
-"// しかし、 b は c に代入できないし、a は d に代入できない\n"
-"c = b;          // エラー\n"
-"~~~~\n"
+#: doc/tutorial.md:963
+#, fuzzy
+#| msgid "# Boxes"
+msgid "## Boxes"
+msgstr "# ボックス"
 
 #. type: Plain text
-#: doc/tutorial.md:1029
-msgid "# Move semantics"
+#: doc/tutorial.md:1032
+#, fuzzy
+#| msgid "# Move semantics"
+msgid "## Move semantics"
 msgstr "# ムーブセマンティクス"
 
 #. type: Plain text
-#: doc/tutorial.md:1035
-msgid ""
-"Rust uses a shallow copy for parameter passing, assignment and returning "
-"values from functions. A shallow copy is considered a move of ownership if "
-"the ownership tree of the copied value includes an owned box or a type with "
-"a custom destructor. After a value has been moved, it can no longer be used "
-"from the source location and will not be destroyed there."
-msgstr ""
-"Rust は関数パラメータの受け渡しや、変数への代入、関数からの戻り値を設定する際"
-"に、シャローコピーを使用しています。コピーされる値の所有権ツリーが所有ボック"
-"スや独自のデストラクタを持つ型を含んでいる場合、シャローコピーは所有権の移動"
-"とみなされます。値の移動が行われた後、元々その値を参照していた箇所からは値を"
-"利用することはできなくなり、もとの所有者から値が破壊されることもありません。"
-
-#. type: Plain text
-#: doc/tutorial.md:1041
+#: doc/tutorial.md:1076
 msgid ""
 "~~~~ let x = ~5; let y = x.clone(); // y is a newly allocated box let z = "
 "x; // no new memory allocated, x can no longer be used ~~~~"
@@ -2463,17 +2121,7 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1044
-msgid ""
-"Since in owned boxes mutability is a property of the owner, not the box, "
-"mutable boxes may become immutable when they are moved, and vice-versa."
-msgstr ""
-"所有ボックスのミュータビリティは、ボックスではなく所有者のミュータビリティを"
-"引き継ぐため、同一のボックスが移動によりミュータブルになったりイミュータブル"
-"になったりすることがありえます。"
-
-#. type: Plain text
-#: doc/tutorial.md:1051
+#: doc/tutorial.md:1105
 msgid ""
 "~~~~ let r = ~13; let mut s = r; // box becomes mutable *s += 1; let t = "
 "s; // box becomes immutable ~~~~"
@@ -2486,18 +2134,59 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1053
-msgid "# Borrowed pointers"
-msgstr "# 借用ポインタ"
+#: doc/tutorial.md:1129
+#, fuzzy
+msgid "## References"
+msgstr "# ポインタのデリファレンス"
+
+#. type: Plain text
+#: doc/tutorial.md:1175
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "## Lists of other types"
+msgstr "## 他のクレートの利用"
+
+#. type: Plain text
+#: doc/tutorial.md:1307
+#, fuzzy
+#| msgid "## Managed boxes"
+msgid "# More on boxes"
+msgstr "## マネージドボックス"
+
+#. type: Plain text
+#: doc/tutorial.md:1338
+msgid "~~~~ let x = 5; // immutable let mut y = 5; // mutable y += 2;"
+msgstr ""
+"~~~~\n"
+"let x = 5; // イミュータブル\n"
+"let mut y = 5; // ミュータブル\n"
+"y += 2;"
+
+#. type: Plain text
+#: doc/tutorial.md:1343
+msgid ""
+"let x = ~5; // immutable let mut y = ~5; // mutable *y += 2; // the * "
+"operator is needed to access the contained value ~~~~"
+msgstr ""
+"let x = ~5; // イミュータブル\n"
+"let mut y = ~5; // ミュータブル\n"
+"*y += 2; // ボックスの中身にアクセスするには、 * 演算子が必要\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1059
+#: doc/tutorial.md:1352
+#, fuzzy
+#| msgid ""
+#| "Rust's borrowed pointers are a general purpose reference type. In "
+#| "contrast with owned boxes, where the holder of an owned box is the owner "
+#| "of the pointed-to memory, borrowed pointers never imply ownership. A "
+#| "pointer can be borrowed to any object, and the compiler verifies that it "
+#| "cannot outlive the lifetime of the object."
 msgid ""
-"Rust's borrowed pointers are a general purpose reference type. In contrast "
-"with owned boxes, where the holder of an owned box is the owner of the "
-"pointed-to memory, borrowed pointers never imply ownership. A pointer can be "
-"borrowed to any object, and the compiler verifies that it cannot outlive the "
-"lifetime of the object."
+"In contrast with owned boxes, where the holder of an owned box is the owner "
+"of the pointed-to memory, references never imply ownership - they are "
+"\"borrowed\".  A reference can be borrowed to any object, and the compiler "
+"verifies that it cannot outlive the lifetime of the object."
 msgstr ""
 "Rust の借用ポインタ (borrowed pointer) は汎用的な参照型です。所有ボックスの場"
 "合、ボックスの所有者が参照されているメモリの所有者となるのに対して、借用ポイ"
@@ -2506,24 +2195,12 @@ msgstr ""
 "生きしないことがコンパイラにより保証されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1061
+#: doc/tutorial.md:1354
 msgid "As an example, consider a simple struct type, `Point`:"
 msgstr "例として、シンプルな構造体型の `Point` について考えます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1068
-#, no-wrap
-msgid ""
-"~~~\n"
-"struct Point {\n"
-"    x: f64,\n"
-"    y: f64\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1072
+#: doc/tutorial.md:1365
 msgid ""
 "We can use this simple definition to allocate points in many different ways. "
 "For example, in this code, each of these three local variables contains a "
@@ -2534,8 +2211,9 @@ msgstr ""
 "なった場所に `Point` 型のオブジェクトを割り当てています。"
 
 #. type: Plain text
-#: doc/tutorial.md:1079
-#, no-wrap
+#: doc/tutorial.md:1372
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
 msgid ""
 "~~~\n"
 "# struct Point { x: f64, y: f64 }\n"
@@ -2544,9 +2222,24 @@ msgid ""
 "let owned_box    : ~Point = ~Point { x: 7.0, y: 9.0 };\n"
 "~~~\n"
 msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
 
 #. type: Plain text
-#: doc/tutorial.md:1089
+#: doc/tutorial.md:1382
+#, fuzzy
+#| msgid ""
+#| "Suppose we want to write a procedure that computes the distance between "
+#| "any two points, no matter where they are stored. For example, we might "
+#| "like to compute the distance between `on_the_stack` and `managed_box`, or "
+#| "between `managed_box` and `owned_box`. One option is to define a function "
+#| "that takes two arguments of type point—that is, it takes the points by "
+#| "value. But this will cause the points to be copied when we call the "
+#| "function. For points, this is probably not so bad, but often copies are "
+#| "expensive. So we’d like to define a function that takes the points by "
+#| "pointer. We can use borrowed pointers to do this:"
 msgid ""
 "Suppose we want to write a procedure that computes the distance between any "
 "two points, no matter where they are stored. For example, we might like to "
@@ -2555,8 +2248,8 @@ msgid ""
 "two arguments of type point—that is, it takes the points by value. But this "
 "will cause the points to be copied when we call the function. For points, "
 "this is probably not so bad, but often copies are expensive. So we’d like to "
-"define a function that takes the points by pointer. We can use borrowed "
-"pointers to do this:"
+"define a function that takes the points by pointer. We can use references to "
+"do this:"
 msgstr ""
 "`Point` 型のオブジェクトの割り当て先がどこであったとしても利用可能な、任意の "
 "2 点間の距離を計算する処理を書きたいとします。例えば、 `on_the_stack`, "
@@ -2570,48 +2263,39 @@ msgstr ""
 "です。"
 
 #. type: Plain text
-#: doc/tutorial.md:1099
-#, no-wrap
-msgid ""
-"~~~\n"
-"# struct Point { x: f64, y: f64 }\n"
-"# fn sqrt(f: f64) -> f64 { 0f }\n"
-"fn compute_distance(p1: &Point, p2: &Point) -> f64 {\n"
-"    let x_d = p1.x - p2.x;\n"
-"    let y_d = p1.y - p2.y;\n"
-"    sqrt(x_d * x_d + y_d * y_d)\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1101 doc/tutorial-borrowed-ptr.md:72
-msgid "Now we can call `compute_distance()` in various ways:"
-msgstr ""
-"上記の `compute_distance()` 関数は、様々な方法で呼び出すことができます。"
-
-#. type: Plain text
-#: doc/tutorial.md:1111
-#, no-wrap
+#: doc/tutorial.md:1404
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} # struct Point { x: f64, y: f64 } let mut mypoint = Point { x: 1.0, y: 1.0 }; let origin = Point { x: 0.0, y: 0.0 };"
 msgid ""
 "~~~\n"
 "# struct Point{ x: f64, y: f64 };\n"
 "# let on_the_stack : Point  =  Point { x: 3.0, y: 4.0 };\n"
 "# let managed_box  : @Point = @Point { x: 5.0, y: 1.0 };\n"
 "# let owned_box    : ~Point = ~Point { x: 7.0, y: 9.0 };\n"
-"# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0f }\n"
+"# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }\n"
 "compute_distance(&on_the_stack, managed_box);\n"
 "compute_distance(managed_box, owned_box);\n"
 "~~~\n"
 msgstr ""
+"~~~~ {.xfail-test}\n"
+"# struct Point { x: f64, y: f64 }\n"
+"let mut mypoint = Point { x: 1.0, y: 1.0 };\n"
+"let origin = Point { x: 0.0, y: 0.0 };"
 
 #. type: Plain text
-#: doc/tutorial.md:1118
+#: doc/tutorial.md:1411
+#, fuzzy
+#| msgid ""
+#| "Here the `&` operator is used to take the address of the variable "
+#| "`on_the_stack`; this is because `on_the_stack` has the type `Point` (that "
+#| "is, a struct value) and we have to take its address to get a value. We "
+#| "also call this _borrowing_ the local variable `on_the_stack`, because we "
+#| "are creating an alias: that is, another route to the same data."
 msgid ""
 "Here the `&` operator is used to take the address of the variable "
 "`on_the_stack`; this is because `on_the_stack` has the type `Point` (that "
-"is, a struct value) and we have to take its address to get a value. We also "
-"call this _borrowing_ the local variable `on_the_stack`, because we are "
+"is, a struct value) and we have to take its address to get a reference. We "
+"also call this _borrowing_ the local variable `on_the_stack`, because we are "
 "creating an alias: that is, another route to the same data."
 msgstr ""
 "ここで `&` 演算子は `on_the_stack` 変数のアドレスを取得するために使われていま"
@@ -2622,13 +2306,20 @@ msgstr ""
 "(_borrowing_) と呼びます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1124
+#: doc/tutorial.md:1417
+#, fuzzy
+#| msgid ""
+#| "In the case of the boxes `managed_box` and `owned_box`, however, no "
+#| "explicit action is necessary. The compiler will automatically convert a "
+#| "box like `@point` or `~point` to a borrowed pointer like `&point`. This "
+#| "is another form of borrowing; in this case, the contents of the managed/"
+#| "owned box are being lent out."
 msgid ""
 "In the case of the boxes `managed_box` and `owned_box`, however, no explicit "
 "action is necessary. The compiler will automatically convert a box like "
-"`@point` or `~point` to a borrowed pointer like `&point`. This is another "
-"form of borrowing; in this case, the contents of the managed/owned box are "
-"being lent out."
+"`@point` or `~point` to a reference like `&point`. This is another form of "
+"borrowing; in this case, the contents of the managed/owned box are being "
+"lent out."
 msgstr ""
 "ボックスである `managed_box` と `owned_box` の場合は、特に明示的な操作を行う"
 "必要はありません。コンパイラは `@point` や `~point` のようなボックスを自動的"
@@ -2637,15 +2328,25 @@ msgstr ""
 "す。"
 
 #. type: Plain text
-#: doc/tutorial.md:1133
+#: doc/tutorial.md:1426
+#, fuzzy
+#| msgid ""
+#| "Whenever a value is borrowed, there are some limitations on what you can "
+#| "do with the original. For example, if the contents of a variable have "
+#| "been lent out, you cannot send that variable to another task, nor will "
+#| "you be permitted to take actions that might cause the borrowed value to "
+#| "be freed or to change its type. This rule should make intuitive sense: "
+#| "you must wait for a borrowed value to be returned (that is, for the "
+#| "borrowed pointer to go out of scope) before you can make full use of it "
+#| "again."
 msgid ""
 "Whenever a value is borrowed, there are some limitations on what you can do "
 "with the original. For example, if the contents of a variable have been lent "
 "out, you cannot send that variable to another task, nor will you be "
 "permitted to take actions that might cause the borrowed value to be freed or "
 "to change its type. This rule should make intuitive sense: you must wait for "
-"a borrowed value to be returned (that is, for the borrowed pointer to go out "
-"of scope) before you can make full use of it again."
+"a borrowed value to be returned (that is, for the reference to go out of "
+"scope) before you can make full use of it again."
 msgstr ""
 "値が借用されている間、借用元の値に対して行える操作がいくらか制限されます。例"
 "えば、変数の内容が貸し出された場合、その変数を他のタスクに送信することはでき"
@@ -2655,29 +2356,34 @@ msgstr ""
 "コープを抜ける) を待たなければなりません。"
 
 #. type: Plain text
-#: doc/tutorial.md:1136
+#: doc/tutorial.md:1429
+#, fuzzy
+#| msgid ""
+#| "For a more in-depth explanation of borrowed pointers, read the [borrowed "
+#| "pointer tutorial][borrowtut]."
 msgid ""
-"For a more in-depth explanation of borrowed pointers, read the [borrowed "
-"pointer tutorial][borrowtut]."
+"For a more in-depth explanation of references and lifetimes, read the "
+"[references and lifetimes guide][lifetimes]."
 msgstr ""
 "借用ポインタの詳細については、[借用ポインタのチュートリアル][borrowtut]を参照"
 "してください。"
 
 #. type: Plain text
-#: doc/tutorial.md:1138
-msgid "[borrowtut]: tutorial-borrowed-ptr.html"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1140
+#: doc/tutorial.md:1431
 msgid "## Freezing"
 msgstr "## 凍結"
 
 #. type: Plain text
-#: doc/tutorial.md:1143
+#: doc/tutorial.md:1435
+#, fuzzy
+#| msgid ""
+#| "Borrowing an immutable pointer to an object freezes it and prevents "
+#| "mutation.  `Owned` objects have freezing enforced statically at compile-"
+#| "time."
 msgid ""
-"Borrowing an immutable pointer to an object freezes it and prevents "
-"mutation.  `Owned` objects have freezing enforced statically at compile-time."
+"Lending an immutable pointer to an object freezes it and prevents mutation.  "
+"`Freeze` objects have freezing enforced statically at compile-time. An "
+"example of a non-`Freeze` type is [`RefCell<T>`][refcell]."
 msgstr ""
 "オブジェクトへのイミュータブルな (借用) ポインタを借用した場合、借用されたオ"
 "ブジェクトは凍結 (freezing) され、変更することができなくなります。`Owned` ト"
@@ -2685,7 +2391,7 @@ msgstr ""
 "されます (凍結された値を変更しようとすると、コンパイルエラーとなります)。"
 
 #. type: Plain text
-#: doc/tutorial.md:1152
+#: doc/tutorial.md:1444
 #, no-wrap
 msgid ""
 "~~~~\n"
@@ -2707,46 +2413,25 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1156
-msgid ""
-"Mutable managed boxes handle freezing dynamically when any of their contents "
-"are borrowed, and the task will fail if an attempt to modify them is made "
-"while they are frozen:"
-msgstr ""
-"ミュータブルなマネージドボックスは、その内容のいずれかが借用される際に動的に"
-"凍結され、凍結状態の間に内容を変更しようとすると、タスクが失敗します。"
-
-#. type: Plain text
-#: doc/tutorial.md:1166
-#, no-wrap
+#: doc/tutorial.md:1446
+#, fuzzy
+#| msgid ""
+#| "[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz [win-exe]: "
+#| "http://static.rust-lang.org/dist/rust-0.7-install.exe"
 msgid ""
-"~~~~\n"
-"let x = @mut 5;\n"
-"let y = x;\n"
-"{\n"
-"    let z = &*y; // the managed box is now frozen\n"
-"    // modifying it through x or y will cause a task failure\n"
-"}\n"
-"// the box is now unfrozen again\n"
-"~~~~\n"
+"[refcell]: http://static.rust-lang.org/doc/master/std/cell/struct.RefCell."
+"html"
 msgstr ""
-"~~~~\n"
-"let x = @mut 5;\n"
-"let y = x;\n"
-"{\n"
-"    let z = &*y; // マネージドボックスが凍結される\n"
-"    // x か y を経由して内容を変更すると、タスクが異常終了する\n"
-"}\n"
-"// ボックスの凍結状態は解除される\n"
-"~~~~\n"
+"[tarball]: http://static.rust-lang.org/dist/rust-0.7.tar.gz\n"
+"[win-exe]: http://static.rust-lang.org/dist/rust-0.7-install.exe"
 
 #. type: Plain text
-#: doc/tutorial.md:1168
+#: doc/tutorial.md:1448
 msgid "# Dereferencing pointers"
 msgstr "# ポインタのデリファレンス"
 
 #. type: Plain text
-#: doc/tutorial.md:1171
+#: doc/tutorial.md:1451
 msgid ""
 "Rust uses the unary star operator (`*`) to access the contents of a box or "
 "pointer, similarly to C."
@@ -2755,7 +2440,7 @@ msgstr ""
 "項スター演算子 (`*`) を使います。"
 
 #. type: Plain text
-#: doc/tutorial.md:1176
+#: doc/tutorial.md:1456
 msgid "~~~ let managed = @10; let owned = ~20; let borrowed = &30;"
 msgstr ""
 "~~~\n"
@@ -2764,14 +2449,14 @@ msgstr ""
 "let borrowed = &30;"
 
 #. type: Plain text
-#: doc/tutorial.md:1179
+#: doc/tutorial.md:1459
 msgid "let sum = *managed + *owned + *borrowed; ~~~"
 msgstr ""
 "let sum = *managed + *owned + *borrowed;\n"
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1183
+#: doc/tutorial.md:1463
 msgid ""
 "Dereferenced mutable pointers may appear on the left hand side of "
 "assignments. Such an assignment modifies the value that the pointer points "
@@ -2781,32 +2466,24 @@ msgstr ""
 "きます。このような代入文は、ポインタが指す値を変更します。"
 
 #. type: Plain text
-#: doc/tutorial.md:1187
-msgid "~~~ let managed = @mut 10; let mut owned = ~20;"
+#: doc/tutorial.md:1467
+#, fuzzy
+#| msgid "~~~ let managed = @mut 10; let mut owned = ~20;"
+msgid "~~~ let managed = @10; let mut owned = ~20;"
 msgstr ""
 "~~~\n"
 "let managed = @mut 10;\n"
 "let mut owned = ~20;"
 
 #. type: Plain text
-#: doc/tutorial.md:1190
+#: doc/tutorial.md:1470
 msgid "let mut value = 30; let borrowed = &mut value;"
 msgstr ""
 "let mut value = 30;\n"
 "let borrowed = &mut value;"
 
 #. type: Plain text
-#: doc/tutorial.md:1195
-#, no-wrap
-msgid ""
-"*managed = *owned + 10;\n"
-"*owned = *borrowed + 100;\n"
-"*borrowed = *managed + 1000;\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1199
+#: doc/tutorial.md:1478
 msgid ""
 "Pointers have high operator precedence, but lower precedence than the dot "
 "operator used for field and method access. This precedence order can "
@@ -2817,12 +2494,20 @@ msgstr ""
 "弧だらけなものになることがあります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1209
+#: doc/tutorial.md:1488
+#, fuzzy
+#| msgid ""
+#| "~~~ # struct Point { x: f64, y: f64 } # enum Shape { Rectangle(Point, "
+#| "Point) } # impl Shape { fn area(&self) -> int { 0 } } let start = @Point "
+#| "{ x: 10f, y: 20f }; let end = ~Point { x: (*start).x + 100f, y: (*start)."
+#| "y + 100f }; let rect = &Rectangle(*start, *end); let area = (*rect)."
+#| "area(); ~~~"
 msgid ""
 "~~~ # struct Point { x: f64, y: f64 } # enum Shape { Rectangle(Point, "
 "Point) } # impl Shape { fn area(&self) -> int { 0 } } let start = @Point "
-"{ x: 10f, y: 20f }; let end = ~Point { x: (*start).x + 100f, y: (*start).y + "
-"100f }; let rect = &Rectangle(*start, *end); let area = (*rect).area(); ~~~"
+"{ x: 10.0, y: 20.0 }; let end = ~Point { x: (*start).x + 100.0, y: (*start)."
+"y + 100.0 }; let rect = &Rectangle(*start, *end); let area = (*rect).area(); "
+"~~~"
 msgstr ""
 "~~~\n"
 "# struct Point { x: f64, y: f64 }\n"
@@ -2835,7 +2520,7 @@ msgstr ""
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1213
+#: doc/tutorial.md:1492
 msgid ""
 "To combat this ugliness the dot operator applies _automatic pointer "
 "dereferencing_ to the receiver (the value on the left-hand side of the dot), "
@@ -2846,12 +2531,18 @@ msgstr ""
 "レシーバを明示的にデリファレンスする必要がなくなります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1223
+#: doc/tutorial.md:1502
+#, fuzzy
+#| msgid ""
+#| "~~~ # struct Point { x: f64, y: f64 } # enum Shape { Rectangle(Point, "
+#| "Point) } # impl Shape { fn area(&self) -> int { 0 } } let start = @Point "
+#| "{ x: 10f, y: 20f }; let end = ~Point { x: start.x + 100f, y: start.y + "
+#| "100f }; let rect = &Rectangle(*start, *end); let area = rect.area(); ~~~"
 msgid ""
 "~~~ # struct Point { x: f64, y: f64 } # enum Shape { Rectangle(Point, "
 "Point) } # impl Shape { fn area(&self) -> int { 0 } } let start = @Point "
-"{ x: 10f, y: 20f }; let end = ~Point { x: start.x + 100f, y: start.y + "
-"100f }; let rect = &Rectangle(*start, *end); let area = rect.area(); ~~~"
+"{ x: 10.0, y: 20.0 }; let end = ~Point { x: start.x + 100.0, y: start.y + "
+"100.0 }; let rect = &Rectangle(*start, *end); let area = rect.area(); ~~~"
 msgstr ""
 "~~~\n"
 "# struct Point { x: f64, y: f64 }\n"
@@ -2864,7 +2555,7 @@ msgstr ""
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1227
+#: doc/tutorial.md:1506
 msgid ""
 "You can write an expression that dereferences any number of pointers "
 "automatically. For example, if you feel inclined, you could write something "
@@ -2874,10 +2565,14 @@ msgstr ""
 "うと思えば以下のような馬鹿げたものを書くこともできます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1233
+#: doc/tutorial.md:1512
+#, fuzzy
+#| msgid ""
+#| "~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: "
+#| "20f }; println(fmt!(\"%f\", point.x)); ~~~"
 msgid ""
-"~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10f, y: "
-"20f }; println(fmt!(\"%f\", point.x)); ~~~"
+"~~~ # struct Point { x: f64, y: f64 } let point = &@~Point { x: 10.0, y: "
+"20.0 }; println!(\"{:f}\", point.x); ~~~"
 msgstr ""
 "~~~\n"
 "# struct Point { x: f64, y: f64 }\n"
@@ -2886,22 +2581,28 @@ msgstr ""
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1235
+#: doc/tutorial.md:1514
 msgid "The indexing operator (`[]`) also auto-dereferences."
 msgstr "添字演算子 (`[]`) も自動でリファレンスを行います。"
 
 #. type: Plain text
-#: doc/tutorial.md:1237
+#: doc/tutorial.md:1516
 msgid "# Vectors and strings"
 msgstr "# ベクタと文字列"
 
 #. type: Plain text
-#: doc/tutorial.md:1242
+#: doc/tutorial.md:1520
+#, fuzzy
+#| msgid ""
+#| "A vector is a contiguous section of memory containing zero or more values "
+#| "of the same type. Like other types in Rust, vectors can be stored on the "
+#| "stack, the local heap, or the exchange heap. Borrowed pointers to vectors "
+#| "are also called 'slices'."
 msgid ""
-"A vector is a contiguous section of memory containing zero or more values of "
-"the same type. Like other types in Rust, vectors can be stored on the stack, "
-"the local heap, or the exchange heap. Borrowed pointers to vectors are also "
-"called 'slices'."
+"A vector is a contiguous block of memory containing zero or more values of "
+"the same type. Rust also supports vector reference types, called slices, "
+"which are a view into a block of memory represented as a pointer and a "
+"length."
 msgstr ""
 "ベクタは同じ型の値が0個以上含まれる、メモリ上の連続した部分のことです。Rust "
 "の他の型と同様、ベクタもスタック、ローカルヒープ、交換ヒープ (exchange heap) "
@@ -2909,394 +2610,62 @@ msgstr ""
 "場合もあります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1252
-#, no-wrap
-msgid ""
-"~~~\n"
-"# enum Crayon {\n"
-"#     Almond, AntiqueBrass, Apricot,\n"
-"#     Aquamarine, Asparagus, AtomicTangerine,\n"
-"#     BananaMania, Beaver, Bittersweet,\n"
-"#     Black, BlizzardBlue, Blue\n"
-"# }\n"
-"// A fixed-size stack vector\n"
-"let stack_crayons: [Crayon, ..3] = [Almond, AntiqueBrass, Apricot];\n"
-msgstr ""
-"~~~\n"
-"# enum Crayon {\n"
-"#     Almond, AntiqueBrass, Apricot,\n"
-"#     Aquamarine, Asparagus, AtomicTangerine,\n"
-"#     BananaMania, Beaver, Bittersweet,\n"
-"#     Black, BlizzardBlue, Blue\n"
-"# }\n"
-"// スタック上の固定長ベクタ\n"
-"let stack_crayons: [Crayon, ..3] = [Almond, AntiqueBrass, Apricot];\n"
-
-#. type: Plain text
-#: doc/tutorial.md:1255
-msgid ""
-"// A borrowed pointer to stack-allocated vector let stack_crayons: &[Crayon] "
-"= &[Aquamarine, Asparagus, AtomicTangerine];"
-msgstr ""
-"// スタックに獲得されたベクタへの借用ポインタ\n"
-"let stack_crayons: &[Crayon] = &[Aquamarine, Asparagus, AtomicTangerine];"
-
-#. type: Plain text
-#: doc/tutorial.md:1258
-msgid ""
-"// A local heap (managed) vector of crayons let local_crayons: @[Crayon] = "
-"@[BananaMania, Beaver, Bittersweet];"
-msgstr ""
-"// ローカルヒープ上に獲得された、クレヨンの (マネージド) ベクタ\n"
-"let local_crayons: @[Crayon] = @[BananaMania, Beaver, Bittersweet];"
-
-#. type: Plain text
-#: doc/tutorial.md:1262
-msgid ""
-"// An exchange heap (owned) vector of crayons let exchange_crayons: "
-"~[Crayon] = ~[Black, BlizzardBlue, Blue]; ~~~"
-msgstr ""
-"// 交換ヒープに獲得された、クレヨンの (所有) ベクタ\n"
-"let exchange_crayons: ~[Crayon] = ~[Black, BlizzardBlue, Blue];\n"
-"~~~"
-
-#. type: Plain text
-#: doc/tutorial.md:1264
-msgid "The `+` operator means concatenation when applied to vector types."
-msgstr "`+` 演算子がベクタ型に適用された場合、ベクタの結合を意味します。"
-
-#. type: Plain text
-#: doc/tutorial.md:1274
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# enum Crayon { Almond, AntiqueBrass, Apricot,\n"
-"#               Aquamarine, Asparagus, AtomicTangerine,\n"
-"#               BananaMania, Beaver, Bittersweet };\n"
-"# impl Clone for Crayon {\n"
-"#     fn clone(&self) -> Crayon {\n"
-"#         *self\n"
-"#     }\n"
-"# }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1277
-msgid ""
-"let my_crayons = ~[Almond, AntiqueBrass, Apricot]; let your_crayons = "
-"~[BananaMania, Beaver, Bittersweet];"
-msgstr ""
-"let my_crayons = ~[Almond, AntiqueBrass, Apricot];\n"
-"let your_crayons = ~[BananaMania, Beaver, Bittersweet];"
-
-#. type: Plain text
-#: doc/tutorial.md:1280
-msgid ""
-"// Add two vectors to create a new one let our_crayons = my_crayons + "
-"your_crayons;"
-msgstr ""
-"// 2 つのベクタを結合して、新しいベクタを作る\n"
-"let our_crayons = my_crayons + your_crayons;"
-
-#. type: Plain text
-#: doc/tutorial.md:1285
-msgid ""
-"// .push_all() will append to a vector, provided it lives in a mutable slot "
-"let mut my_crayons = my_crayons; my_crayons.push_all(your_crayons); ~~~~"
-msgstr ""
-"// .push_all() はベクタに要素を追加します。ミュータブルなスロットのベクタに対"
-"してのみ有効です\n"
-"let mut my_crayons = my_crayons;\n"
-"my_crayons.push_all(your_crayons);\n"
-"~~~~"
-
-#. type: Plain text
-#: doc/tutorial.md:1290
-msgid ""
-"> ***Note:*** The above examples of vector addition use owned > vectors. "
-"Some operations on slices and stack vectors are > not yet well-supported. "
-"Owned vectors are often the most > usable."
-msgstr ""
-"> ***注意:*** 上記のベクタに要素を追加する例では、所有ベクタを利用していま"
-"す。いくつかの操作はスライスやスタックベクタを十分にサポートしていません。所"
-"有ベクタが最も便利な場合がしばしばあります。"
-
-#. type: Plain text
-#: doc/tutorial.md:1292
+#: doc/tutorial.md:1593
 msgid "Square brackets denote indexing into a vector:"
 msgstr "角括弧はベクタの添字を表します。"
 
 #. type: Plain text
-#: doc/tutorial.md:1304
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# enum Crayon { Almond, AntiqueBrass, Apricot,\n"
-"#               Aquamarine, Asparagus, AtomicTangerine,\n"
-"#               BananaMania, Beaver, Bittersweet };\n"
-"# fn draw_scene(c: Crayon) { }\n"
-"let crayons: [Crayon, ..3] = [BananaMania, Beaver, Bittersweet];\n"
-"match crayons[0] {\n"
-"    Bittersweet => draw_scene(crayons[0]),\n"
-"    _ => ()\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1306
+#: doc/tutorial.md:1607
 msgid "A vector can be destructured using pattern matching:"
 msgstr "ベクタはパターンマッチにより destructuring することができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1316
-#, no-wrap
-msgid ""
-"~~~~\n"
-"let numbers: &[int] = &[1, 2, 3];\n"
-"let score = match numbers {\n"
-"    [] => 0,\n"
-"    [a] => a * 10,\n"
-"    [a, b] => a * 6 + b * 4,\n"
-"    [a, b, c, ..rest] => a * 5 + b * 3 + c * 2 + rest.len() as int\n"
-"};\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1320
-msgid ""
-"The elements of a vector _inherit the mutability of the vector_, and as "
-"such, individual elements may not be reassigned when the vector lives in an "
-"immutable slot."
-msgstr ""
-"ベクタの要素は、 __ベクタのミュータビリティを継承するので__、ベクタがイミュー"
-"タブルなスロットに格納されている場合は個々の要素を変更する (再代入する) こと"
-"はできません。"
-
-#. type: Plain text
-#: doc/tutorial.md:1326
-#, no-wrap
-msgid ""
-"~~~ {.xfail-test}\n"
-"# enum Crayon { Almond, AntiqueBrass, Apricot,\n"
-"#               Aquamarine, Asparagus, AtomicTangerine,\n"
-"#               BananaMania, Beaver, Bittersweet };\n"
-"let crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1329
-msgid "crayons[0] = Apricot; // ERROR: Can't assign to immutable vector ~~~"
-msgstr ""
-"crayons[0] = Apricot; // ERROR: Can't assign to immutable vector\n"
-"~~~"
-
-#. type: Plain text
-#: doc/tutorial.md:1331
-msgid "Moving it into a mutable slot makes the elements assignable."
-msgstr ""
-"ベクタをミュータブルなスロットに移動することで、要素への代入が可能になりま"
-"す。"
-
-#. type: Plain text
-#: doc/tutorial.md:1337
-#, no-wrap
-msgid ""
-"~~~\n"
-"# enum Crayon { Almond, AntiqueBrass, Apricot,\n"
-"#               Aquamarine, Asparagus, AtomicTangerine,\n"
-"#               BananaMania, Beaver, Bittersweet };\n"
-"let crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1340
-msgid ""
-"// Put the vector into a mutable slot let mut mutable_crayons = crayons;"
-msgstr ""
-"// ベクタをミュータブルなスロットに配置する\n"
-"let mut mutable_crayons = crayons;"
-
-#. type: Plain text
-#: doc/tutorial.md:1344
-msgid "// Now it's mutable to the bone mutable_crayons[0] = Apricot; ~~~"
-msgstr ""
-"// 完全にミュータブルになった\n"
-"mutable_crayons[0] = Apricot;\n"
-"~~~"
-
-#. type: Plain text
-#: doc/tutorial.md:1347
-msgid ""
-"This is a simple example of Rust's _dual-mode data structures_, also "
-"referred to as _freezing and thawing_."
-msgstr ""
-"これは、__凍結および解凍__ (_freezing and thawing_) と呼ばれる、Rust の __"
-"デュアルモードのデータ構造__ についての簡単な例です。"
-
-#. type: Plain text
-#: doc/tutorial.md:1355
-msgid ""
-"Strings are implemented with vectors of `u8`, though they have a distinct "
-"type. They support most of the same allocation options as vectors, though "
-"the string literal without a storage sigil (for example, `\"foo\"`) is "
-"treated differently than a comparable vector (`[foo]`).  Whereas plain "
-"vectors are stack-allocated fixed-length vectors, plain strings are borrowed "
-"pointers to read-only (static)  memory. All strings are immutable."
-msgstr ""
-"文字列は `u8` 型のベクタとして実装されていますが、ベクタとは異なる独自の型を"
-"持ちます。文字列はベクタと同じくメモリを獲得先を選択できますが、ストレージを"
-"表すシジルが付与されていない文字列リテラル (`\"foo\"` など) は対応するベクタ "
-"(`[foo]`) と異なった扱いをされます。シジルなしのベクタはスタックに獲得される"
-"固定長のベクタですが、シジルなしの文字列は読み込み専用の (静的な) メモリ領域"
-"への借用ポインタとなります。すべての文字列はイミュータブルです。"
-
-#. type: Plain text
-#: doc/tutorial.md:1359
-msgid ""
-"~~~ // A plain string is a slice to read-only (static) memory let "
-"stack_crayons: &str = \"Almond, AntiqueBrass, Apricot\";"
-msgstr ""
-"~~~\n"
-"// シジルなしの文字列は、読み込み専用な (静的) メモリへのスライス\n"
-"let stack_crayons: &str = \"Almond, AntiqueBrass, Apricot\";"
-
-#. type: Plain text
-#: doc/tutorial.md:1362
-msgid ""
-"// The same thing, but with the `&` let stack_crayons: &str = &\"Aquamarine, "
-"Asparagus, AtomicTangerine\";"
-msgstr ""
-"// `&` を付与した場合も、シジルなしと同じ意味\n"
-"let stack_crayons: &str = &\"Aquamarine, Asparagus, AtomicTangerine\";"
-
-#. type: Plain text
-#: doc/tutorial.md:1365
-msgid ""
-"// A local heap (managed) string let local_crayons: @str = @\"BananaMania, "
-"Beaver, Bittersweet\";"
-msgstr ""
-"// ローカルヒープ上の (マネージドな) 文字列\n"
-"let local_crayons: @str = @\"BananaMania, Beaver, Bittersweet\";"
-
-#. type: Plain text
-#: doc/tutorial.md:1369
-msgid ""
-"// An exchange heap (owned) string let exchange_crayons: ~str = ~\"Black, "
-"BlizzardBlue, Blue\"; ~~~"
-msgstr ""
-"// 交換ヒープ上の (所有) 文字列\n"
-"let exchange_crayons: ~str = ~\"Black, BlizzardBlue, Blue\";\n"
-"~~~"
-
-#. type: Plain text
-#: doc/tutorial.md:1373
+#: doc/tutorial.md:1620
+#, fuzzy
+#| msgid ""
+#| "Both vectors and strings support a number of useful [methods](#methods), "
+#| "defined in [`std::vec`] and [`std::str`]. Here are some examples."
 msgid ""
 "Both vectors and strings support a number of useful [methods](#methods), "
-"defined in [`std::vec`] and [`std::str`]. Here are some examples."
+"defined in [`std::vec`] and [`std::str`]."
 msgstr ""
 "ベクタと文字列は、[`std::vec`] と [`std::str`] で定義された、多くの有用な [メ"
 "ソッド](#methods) を持ちます。以下にいくつか例を挙げます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1376
-msgid "[`std::vec`]: std/vec.html [`std::str`]: std/str.html"
+#: doc/tutorial.md:1623
+#, fuzzy
+#| msgid "[`std::vec`]: std/vec.html [`std::str`]: std/str.html"
+msgid "[`std::vec`]: std/vec/index.html [`std::str`]: std/str/index.html"
 msgstr ""
 "[`std::vec`]: std/vec.html\n"
 "[`std::str`]: std/str.html"
 
 #. type: Plain text
-#: doc/tutorial.md:1387
-#, no-wrap
-msgid ""
-"~~~\n"
-"# enum Crayon {\n"
-"#     Almond, AntiqueBrass, Apricot,\n"
-"#     Aquamarine, Asparagus, AtomicTangerine,\n"
-"#     BananaMania, Beaver, Bittersweet\n"
-"# }\n"
-"# fn unwrap_crayon(c: Crayon) -> int { 0 }\n"
-"# fn eat_crayon_wax(i: int) { }\n"
-"# fn store_crayon_in_nasal_cavity(i: uint, c: Crayon) { }\n"
-"# fn crayon_to_str(c: Crayon) -> &str { \"\" }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1389
-msgid "let crayons = [Almond, AntiqueBrass, Apricot];"
+#: doc/tutorial.md:1635
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~ use std::rc::Rc;"
 msgstr ""
+"~~~~\n"
+"use std::task::spawn;"
 
 #. type: Plain text
-#: doc/tutorial.md:1393
-msgid ""
-"// Check the length of the vector assert!(crayons.len() == 3); assert!(!"
-"crayons.is_empty());"
-msgstr ""
-"// ベクタの長さをチェックする\n"
-"assert!(crayons.len() == 3);\n"
-"assert!(!crayons.is_empty());"
-
-#. type: Plain text
-#: doc/tutorial.md:1400
-#, no-wrap
-msgid ""
-"// Iterate over a vector, obtaining a pointer to each element\n"
-"// (`for` is explained in the container/iterator tutorial)\n"
-"for crayon in crayons.iter() {\n"
-"    let delicious_crayon_wax = unwrap_crayon(*crayon);\n"
-"    eat_crayon_wax(delicious_crayon_wax);\n"
-"}\n"
-msgstr ""
-"// ベクタの要素をイテレートし、各要素へのポインタを取得する\n"
-"// (`for` については、は次の章で説明します)\n"
-"for crayon in crayons.iter() {\n"
-"    let delicious_crayon_wax = unwrap_crayon(*crayon);\n"
-"    eat_crayon_wax(delicious_crayon_wax);\n"
-"}\n"
-
-#. type: Plain text
-#: doc/tutorial.md:1404
-msgid ""
-"// Map vector elements let crayon_names = crayons.map(|v| "
-"crayon_to_str(*v)); let favorite_crayon_name = crayon_names[0];"
-msgstr ""
-"// ベクタの要素をマッピング (変換) する\n"
-"let crayon_names = crayons.map(|v| crayon_to_str(*v));\n"
-"let favorite_crayon_name = crayon_names[0];"
-
-#. type: Plain text
-#: doc/tutorial.md:1407
-msgid ""
-"// Remove whitespace from before and after the string let "
-"new_favorite_crayon_name = favorite_crayon_name.trim();"
-msgstr ""
-"// 文字列の先頭と末尾の空白を除去する\n"
-"let new_favorite_crayon_name = favorite_crayon_name.trim();"
-
-#. type: Plain text
-#: doc/tutorial.md:1413
-#, no-wrap
-msgid ""
-"if favorite_crayon_name.len() > 5 {\n"
-"   // Create a substring\n"
-"   println(favorite_crayon_name.slice_chars(0, 5));\n"
-"}\n"
-"~~~\n"
+#: doc/tutorial.md:1654
+#, fuzzy
+#| msgid "~~~~ use std::task::spawn;"
+msgid "~~~ use std::gc::Gc;"
 msgstr ""
-"if favorite_crayon_name.len() > 5 {\n"
-"   // 部分文字列を作る\n"
-"   println(favorite_crayon_name.slice_chars(0, 5));\n"
-"}\n"
-"~~~\n"
+"~~~~\n"
+"use std::task::spawn;"
 
 #. type: Plain text
-#: doc/tutorial.md:1415
+#: doc/tutorial.md:1671
 msgid "# Closures"
 msgstr "# クロージャ"
 
 #. type: Plain text
-#: doc/tutorial.md:1420
+#: doc/tutorial.md:1676
 msgid ""
 "Named functions, like those we've seen so far, may not refer to local "
 "variables declared outside the function: they do not close over their "
@@ -3309,14 +2678,14 @@ msgstr ""
 "コードを書くことはできません。"
 
 #. type: Plain text
-#: doc/tutorial.md:1423
+#: doc/tutorial.md:1679
 msgid "~~~~ {.ignore} let foo = 10;"
 msgstr ""
 "~~~~ {.ignore}\n"
 "let foo = 10;"
 
 #. type: Plain text
-#: doc/tutorial.md:1428
+#: doc/tutorial.md:1684
 #, no-wrap
 msgid ""
 "fn bar() -> int {\n"
@@ -3330,7 +2699,7 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1431
+#: doc/tutorial.md:1687
 msgid ""
 "Rust also supports _closures_, functions that can access variables in the "
 "enclosing scope."
@@ -3339,31 +2708,35 @@ msgstr ""
 "ポートしています。"
 
 #. type: Plain text
-#: doc/tutorial.md:1434
+#: doc/tutorial.md:1690
 msgid "~~~~ fn call_closure_with_ten(b: |int|) { b(10); }"
 msgstr ""
 "~~~~\n"
 "fn call_closure_with_ten(b: |int|) { b(10); }"
 
 #. type: Plain text
-#: doc/tutorial.md:1437
+#: doc/tutorial.md:1693
+#, fuzzy
+#| msgid ""
+#| "let captured_var = 20; let closure = |arg| println(fmt!(\"captured_var="
+#| "%d, arg=%d\", captured_var, arg));"
 msgid ""
-"let captured_var = 20; let closure = |arg| println(fmt!(\"captured_var=%d, "
-"arg=%d\", captured_var, arg));"
+"let captured_var = 20; let closure = |arg| println!(\"captured_var={}, "
+"arg={}\", captured_var, arg);"
 msgstr ""
 "let captured_var = 20;\n"
 "let closure = |arg| println(fmt!(\"captured_var=%d, arg=%d\", captured_var, "
 "arg));"
 
 #. type: Plain text
-#: doc/tutorial.md:1440
+#: doc/tutorial.md:1696
 msgid "call_closure_with_ten(closure); ~~~~"
 msgstr ""
 "call_closure_with_ten(closure);\n"
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1446
+#: doc/tutorial.md:1702
 msgid ""
 "Closures begin with the argument list between vertical bars and are followed "
 "by a single expression. Remember that a block, `{ <expr1>; <expr2>; ... }`, "
@@ -3377,7 +2750,7 @@ msgstr ""
 "場合、ブロックの値は最後の式の値となり、そうでなければ `()` となります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1451
+#: doc/tutorial.md:1707
 msgid ""
 "The types of the arguments are generally omitted, as is the return type, "
 "because the compiler can almost always infer them. In the rare case where "
@@ -3389,7 +2762,7 @@ msgstr ""
 "場合は、引数と戻り値の型注釈を付けることがあります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1455
+#: doc/tutorial.md:1711
 msgid "~~~~ let square = |x: int| -> uint { (x * x) as uint }; ~~~~"
 msgstr ""
 "~~~~\n"
@@ -3397,7 +2770,7 @@ msgstr ""
 "~~~~~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1459
+#: doc/tutorial.md:1715
 msgid ""
 "There are several forms of closure, each with its own role. The most common, "
 "called a _stack closure_, has type `||` and can directly access local "
@@ -3408,7 +2781,7 @@ msgstr ""
 "カル変数に直接アクセスすることができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1464
+#: doc/tutorial.md:1720
 msgid "~~~~ let mut max = 0; [1, 2, 3].map(|x| if *x > max { max = *x }); ~~~~"
 msgstr ""
 "~~~~\n"
@@ -3417,7 +2790,7 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1473
+#: doc/tutorial.md:1729
 msgid ""
 "Stack closures are very efficient because their environment is allocated on "
 "the call stack and refers by pointer to captured locals. To ensure that "
@@ -3435,120 +2808,53 @@ msgstr ""
 "ず、スタッククロージャは Rust のコードのあちこちに登場します。"
 
 #. type: Plain text
-#: doc/tutorial.md:1475
-msgid "## Managed closures"
-msgstr "## マネージドクロージャ"
-
-#. type: Plain text
-#: doc/tutorial.md:1481
-msgid ""
-"When you need to store a closure in a data structure, a stack closure will "
-"not do, since the compiler will refuse to let you store it. For this "
-"purpose, Rust provides a type of closure that has an arbitrary lifetime, "
-"written `@fn` (boxed closure, analogous to the `@` pointer type described "
-"earlier). This type of closure *is* first-class."
-msgstr ""
-"クロージャをデータ構造に格納する必要がある場合、スタッククロージャを利用する"
-"ことは言語仕様上、許可されていませんRust は、このような目的のために任意の寿命"
-"を持つクロージャ型、`@fn` (ボックスクロージャ、 前述の `@` ポインタ型と似たよ"
-"うなもの) を提供しています。この種のクロージャ **は** 第一級の値です。"
-
-#. type: Plain text
-#: doc/tutorial.md:1486
-msgid ""
-"A managed closure does not directly access its environment, but merely "
-"copies out the values that it closes over into a private data structure. "
-"This means that it can not assign to these variables, and cannot observe "
-"updates to them."
-msgstr ""
-"マネージドクロージャは環境に直接アクセスすることはできませんが、単に値をコ"
-"ピーしてプライベートなデータ構造に閉じ込めます。これは、クロージャは変数に値"
-"を代入することや、値の変更を監視することもできません。"
-
-#. type: Plain text
-#: doc/tutorial.md:1489
-msgid ""
-"This code creates a closure that adds a given string to its argument, "
-"returns it from a function, and then calls it:"
-msgstr ""
-"このコードは、与えられた文字列を引数に追加するクロージャを返却する関数と、そ"
-"の呼び出しです。"
-
-#. type: Plain text
-#: doc/tutorial.md:1495
-#, no-wrap
-msgid ""
-"~~~~\n"
-"fn mk_appender(suffix: ~str) -> @fn(~str) -> ~str {\n"
-"    // The compiler knows that we intend this closure to be of type @fn\n"
-"    return |s| s + suffix;\n"
-"}\n"
-msgstr ""
-"~~~~\n"
-"fn mk_appender(suffix: ~str) -> @fn(~str) -> ~str {\n"
-"    // コンパイラはこのクロージャが @fn 型であることを推論します\n"
-"    return |s| s + suffix;\n"
-"}\n"
-
-#. type: Plain text
-#: doc/tutorial.md:1501
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"    let shout = mk_appender(~\"!\");\n"
-"    println(shout(~\"hey ho, let's go\"));\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1503
+#: doc/tutorial.md:1731
 msgid "## Owned closures"
 msgstr "## 所有クロージャ"
 
 #. type: Plain text
-#: doc/tutorial.md:1510
+#: doc/tutorial.md:1738
 msgid ""
-"Owned closures, written `proc`, hold on to "
-"things that can safely be sent between processes. They copy the values they "
-"close over, much like managed closures, but they also own them: that is, no "
-"other code can access them. Owned closures are used in concurrent code, "
-"particularly for spawning [tasks][tasks]."
+"Owned closures, written `proc`, hold on to things that can safely be sent "
+"between processes. They copy the values they close over, much like managed "
+"closures, but they also own them: that is, no other code can access them. "
+"Owned closures are used in concurrent code, particularly for spawning [tasks]"
+"[tasks]."
 msgstr ""
-"`~` `proc` で書き表される所有クロージャは安全にプロセス"
-"間で送信することができます。所有クローじゃはマネージドクロージャと全く同じよ"
-"ã\81\86ã\81«é\96\89ã\81\98è¾¼ã\82\81ã\82\8bå\80¤ã\82\92ã\82³ã\83\94ã\83¼ã\81\97ã\81¾ã\81\99ã\81\8cã\80\81å\80¤ã\82\92æ\89\80æ\9c\89ã\81\97ã\81¾ã\81\99ã\80\82ã\81¤ã\81¾ã\82\8aã\80\81ä»\96ã\81®ã\82³ã\83¼ã\83\89ã\81¯é\96\89ã\81\98è¾¼"
-"ã\82\81ã\82\89ã\82\8cã\81\9få\80¤ã\81«ã\82¢ã\82¯ã\82»ã\82¹ã\81§ã\81\8dã\81ªã\81\8fã\81ªã\82\8aã\81¾ã\81\99ã\80\82æ\89\80æ\9c\89ã\82¯ã\83­ã\83¼ã\82¸ã\83£ã\81¯ä¸¦å\88\97ã\83\97ã\83­ã\82°ã\83©ã\83 ã\80\81ç\89¹ã\81« "
-"[タスク][tasks] 生成で利用されます。"
+"`~` `proc` で書き表される所有クロージャは安全にプロセス間で送信することができ"
+"ます。所有クローじゃはマネージドクロージャと全く同じように閉じ込める値をコ"
+"ã\83\94ã\83¼ã\81\97ã\81¾ã\81\99ã\81\8cã\80\81å\80¤ã\82\92æ\89\80æ\9c\89ã\81\97ã\81¾ã\81\99ã\80\82ã\81¤ã\81¾ã\82\8aã\80\81ä»\96ã\81®ã\82³ã\83¼ã\83\89ã\81¯é\96\89ã\81\98è¾¼ã\82\81ã\82\89ã\82\8cã\81\9få\80¤ã\81«ã\82¢ã\82¯ã\82»ã\82¹"
+"ã\81§ã\81\8dã\81ªã\81\8fã\81ªã\82\8aã\81¾ã\81\99ã\80\82æ\89\80æ\9c\89ã\82¯ã\83­ã\83¼ã\82¸ã\83£ã\81¯ä¸¦å\88\97ã\83\97ã\83­ã\82°ã\83©ã\83 ã\80\81ç\89¹ã\81« [ã\82¿ã\82¹ã\82¯][tasks] ç\94\9fæ\88\90ã\81§"
+"利用されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1512
+#: doc/tutorial.md:1740
 msgid "## Closure compatibility"
 msgstr "## クロージャの互換性"
 
 #. type: Plain text
-#: doc/tutorial.md:1519
+#: doc/tutorial.md:1747
 msgid ""
 "Rust closures have a convenient subtyping property: you can pass any kind of "
 "closure (as long as the arguments and return types match) to functions that "
 "expect a `||`. Thus, when writing a higher-order function that only calls "
 "its function argument, and does nothing else with it, you should almost "
-"always declare the type of that argument as `||`. That way, callers may "
-"pass any kind of closure."
+"always declare the type of that argument as `||`. That way, callers may pass "
+"any kind of closure."
 msgstr ""
 "Rust のクロージャは型の派生 (subtyping) という便利な性質を持っています。この"
-"性質により、`||` 型を期待する関数には (引数と戻り値の型が一致する限り) 任"
-"意の種類のクロージャを渡すことができます。したがって、引数で渡された関数につ"
-"ã\81\84ã\81¦ã\81¯å\91¼ã\81³å\87ºã\81\99ã\81 ã\81\91ã\81§ä»\96ã\81«ä½\95ã\82\82ã\81\97ã\81ªã\81\84é«\98é\9a\8eé\96¢æ\95°ã\82\92æ\9b¸ã\81\8fã\81¨ã\81\8dã\81«ã\81¯ã\80\81ã\81»ã\81¼ã\81\99ã\81¹ã\81¦ã\81®ã\82±ã\83¼ã\82¹"
-"で引数の型を `||` と宣言するべきです。そうすることで、呼び出し元は任意の種類"
-"ã\81®ã\82¯ã\83­ã\83¼ã\82¸ã\83£ã\82\92渡ã\81\99ã\81\93ã\81¨ã\81\8cã\81§ã\81\8dã\82\8bã\82\88ã\81«ã\81ªã\82\8aã\81¾ã\81\99ã\80\82"
+"性質により、`||` 型を期待する関数には (引数と戻り値の型が一致する限り) 任意の"
+"種類のクロージャを渡すことができます。したがって、引数で渡された関数について"
+"ã\81¯å\91¼ã\81³å\87ºã\81\99ã\81 ã\81\91ã\81§ä»\96ã\81«ä½\95ã\82\82ã\81\97ã\81ªã\81\84é«\98é\9a\8eé\96¢æ\95°ã\82\92æ\9b¸ã\81\8fã\81¨ã\81\8dã\81«ã\81¯ã\80\81ã\81»ã\81¼ã\81\99ã\81¹ã\81¦ã\81®ã\82±ã\83¼ã\82¹ã\81§å¼\95"
+"数の型を `||` と宣言するべきです。そうすることで、呼び出し元は任意の種類のク"
+"ロージャを渡すことができるよになります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1527
+#: doc/tutorial.md:1755
 msgid ""
-"~~~~ fn call_twice(f: ||) { f(); f(); } let closure = || { \"I'm a "
-"closure, and it doesn't matter what type I am\"; }; fn function() { \"I'm a "
-"normal function\"; } call_twice(closure); call_twice(function); ~~~~"
+"~~~~ fn call_twice(f: ||) { f(); f(); } let closure = || { \"I'm a closure, "
+"and it doesn't matter what type I am\"; }; fn function() { \"I'm a normal "
+"function\"; } call_twice(closure); call_twice(function); ~~~~"
 msgstr ""
 "~~~~\n"
 "fn call_twice(f: ||) { f(); f(); }\n"
@@ -3560,7 +2866,7 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1531
+#: doc/tutorial.md:1759
 msgid ""
 "> ***Note:*** Both the syntax and the semantics will be changing > in small "
 "ways. At the moment they can be unsound in some > scenarios, particularly "
@@ -3571,45 +2877,25 @@ msgstr ""
 "舞いが起こされる場合があります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1533
+#: doc/tutorial.md:1761
 msgid "## Do syntax"
 msgstr "## do 構文"
 
 #. type: Plain text
-#: doc/tutorial.md:1536
+#: doc/tutorial.md:1764
+#, fuzzy
+#| msgid ""
+#| "The `do` expression provides a way to treat higher-order functions "
+#| "(functions that take closures as arguments) as control structures."
 msgid ""
-"The `do` expression provides a way to treat higher-order functions "
-"(functions that take closures as arguments) as control structures."
+"The `do` expression makes it easier to call functions that take procedures "
+"as arguments."
 msgstr ""
 "`do` 式は高階関数 (クロージャを引数にとる関数) を制御構造のように取り扱う方法"
 "を提供します。"
 
 #. type: Plain text
-#: doc/tutorial.md:1539
-msgid ""
-"Consider this function that iterates over a vector of integers, passing in a "
-"pointer to each integer in the vector:"
-msgstr ""
-"要素が整数のベクトルをイテレートし、各整数へのポインタをクロージャへと渡す、"
-"以下の関数について考えます。"
-
-#. type: Plain text
-#: doc/tutorial.md:1549
-#, no-wrap
-msgid ""
-"~~~~\n"
-"fn each(v: &[int], op: |v: &int|) {\n"
-"   let mut n = 0;\n"
-"   while n < v.len() {\n"
-"       op(&v[n]);\n"
-"       n += 1;\n"
-"   }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1553
+#: doc/tutorial.md:1776
 msgid ""
 "As a caller, if we use a closure to provide the final operator argument, we "
 "can write it in a way that has a pleasant, block-like structure."
@@ -3618,52 +2904,35 @@ msgstr ""
 "コードを書くことが可能です。"
 
 #. type: Plain text
-#: doc/tutorial.md:1561
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# fn each(v: &[int], op: |v: &int|) { }\n"
-"# fn do_some_work(i: &int) { }\n"
-"each([1, 2, 3], |n| {\n"
-"    do_some_work(n);\n"
-"});\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1564
+#: doc/tutorial.md:1786
+#, fuzzy
+#| msgid ""
+#| "This is such a useful pattern that Rust has a special form of function "
+#| "call that can be written more like a built-in control structure:"
 msgid ""
 "This is such a useful pattern that Rust has a special form of function call "
-"that can be written more like a built-in control structure:"
+"for these functions."
 msgstr ""
 "このような便利なパターンに対応するため、Rust には、言語組み込みの制御構造のよ"
 "うな記述が可能な、特別な関数呼び出し形式があります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1572
-#, no-wrap
+#: doc/tutorial.md:1798
+#, fuzzy
+#| msgid ""
+#| "The call is prefixed with the keyword `do` and, instead of writing the "
+#| "final closure inside the argument list, it appears outside of the "
+#| "parentheses, where it looks more like a typical block of code."
 msgid ""
-"~~~~\n"
-"# fn each(v: &[int], op: |v: &int|) { }\n"
-"# fn do_some_work(i: &int) { }\n"
-"do each([1, 2, 3]) |n| {\n"
-"    do_some_work(n);\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1577
-msgid ""
-"The call is prefixed with the keyword `do` and, instead of writing the final "
-"closure inside the argument list, it appears outside of the parentheses, "
-"where it looks more like a typical block of code."
+"The call is prefixed with the keyword `do` and, instead of writing the final "
+"procedure inside the argument list, it appears outside of the parentheses, "
+"where it looks more like a typical block of code."
 msgstr ""
 "関数呼び出しの前には `do` キーワードをつけ、引数リストの中に最後のクロージャ"
 "引数を書くのではなく、普通のコードブロックのように、丸括弧の外に記述します。"
 
 #. type: Plain text
-#: doc/tutorial.md:1582
+#: doc/tutorial.md:1803
 msgid ""
 "`do` is a convenient way to create tasks with the `task::spawn` function.  "
 "`spawn` has the signature `spawn(fn: proc())`. In other words, it is a "
@@ -3675,24 +2944,14 @@ msgstr ""
 "す。"
 
 #. type: Plain text
-#: doc/tutorial.md:1585 doc/tutorial.md:1597
+#: doc/tutorial.md:1806 doc/tutorial.md:1818
 msgid "~~~~ use std::task::spawn;"
 msgstr ""
 "~~~~\n"
 "use std::task::spawn;"
 
 #. type: Plain text
-#: doc/tutorial.md:1590
-#, no-wrap
-msgid ""
-"do spawn() || {\n"
-"    debug!(\"I'm a task, whatever\");\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1594
+#: doc/tutorial.md:1815
 msgid ""
 "Look at all those bars and parentheses -- that's two empty argument lists "
 "back to back. Since that is so unsightly, empty argument lists may be "
@@ -3703,17 +2962,7 @@ msgstr ""
 "が可能です。"
 
 #. type: Plain text
-#: doc/tutorial.md:1602
-#, no-wrap
-msgid ""
-"do spawn {\n"
-"   debug!(\"Kablam!\");\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1605
+#: doc/tutorial.md:1826
 msgid ""
 "If you want to see the output of `debug!` statements, you will need to turn "
 "on `debug!` logging.  To enable `debug!` logging, set the RUST_LOG "
@@ -3727,12 +2976,12 @@ msgstr ""
 "は `foo` になります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1607
+#: doc/tutorial.md:1828
 msgid "# Methods"
 msgstr "# メソッド"
 
 #. type: Plain text
-#: doc/tutorial.md:1613
+#: doc/tutorial.md:1834
 msgid ""
 "Methods are like functions except that they always begin with a special "
 "argument, called `self`, which has the type of the method's receiver. The "
@@ -3744,7 +2993,7 @@ msgstr ""
 "のです。メソッドはドット記法を浸かって `my_vec.len()` のように呼び出します。"
 
 #. type: Plain text
-#: doc/tutorial.md:1617
+#: doc/tutorial.md:1838
 msgid ""
 "_Implementations_, written with the `impl` keyword, can define methods on "
 "most Rust types, including structs and enums.  As an example, let's define a "
@@ -3755,52 +3004,17 @@ msgstr ""
 "す。例のように、 `draw` メソッドを `Shape` 列挙型に定義してみましょう。"
 
 #. type: Plain text
-#: doc/tutorial.md:1625
-#, no-wrap
-msgid ""
-"~~~\n"
-"# fn draw_circle(p: Point, f: f64) { }\n"
-"# fn draw_rectangle(p: Point, p: Point) { }\n"
-"struct Point {\n"
-"    x: f64,\n"
-"    y: f64\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1630
-#, no-wrap
-msgid ""
-"enum Shape {\n"
-"    Circle(Point, f64),\n"
-"    Rectangle(Point, Point)\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1639
-#, no-wrap
-msgid ""
-"impl Shape {\n"
-"    fn draw(&self) {\n"
-"        match *self {\n"
-"            Circle(p, f) => draw_circle(p, f),\n"
-"            Rectangle(p1, p2) => draw_rectangle(p1, p2)\n"
-"        }\n"
-"    }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1643
-msgid "let s = Circle(Point { x: 1f, y: 2f }, 3f); s.draw(); ~~~"
+#: doc/tutorial.md:1864
+#, fuzzy
+#| msgid "let s = Circle(Point { x: 1f, y: 2f }, 3f); s.draw(); ~~~"
+msgid "let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0); s.draw(); ~~~"
 msgstr ""
 "let s = Circle(Point { x: 1f, y: 2f }, 3f);\n"
 "s.draw();\n"
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1647
+#: doc/tutorial.md:1868
 msgid ""
 "This defines an _implementation_ for `Shape` containing a single method, "
 "`draw`. In most respects the `draw` method is defined like any other "
@@ -3811,7 +3025,7 @@ msgstr ""
 "うに定義されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1652
+#: doc/tutorial.md:1873
 msgid ""
 "The type of `self` is the type on which the method is implemented, or a "
 "pointer thereof. As an argument it is written either `self`, `&self`, "
@@ -3823,8 +3037,26 @@ msgstr ""
 "様、メソッドを呼び出すための互換性のあるポインタ型をもつ必要があります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1667
-#, no-wrap
+#: doc/tutorial.md:1888
+#, fuzzy, no-wrap
+#| msgid ""
+#| "~~~\n"
+#| "# fn draw_circle(p: Point, f: f64) { }\n"
+#| "# fn draw_rectangle(p: Point, p: Point) { }\n"
+#| "# struct Point { x: f64, y: f64 }\n"
+#| "# enum Shape {\n"
+#| "#     Circle(Point, f64),\n"
+#| "#     Rectangle(Point, Point)\n"
+#| "# }\n"
+#| "# impl Shape {\n"
+#| "#    fn draw_borrowed(&self) { ... }\n"
+#| "#    fn draw_managed(@self) { ... }\n"
+#| "#    fn draw_owned(~self) { ... }\n"
+#| "#    fn draw_value(self) { ... }\n"
+#| "# }\n"
+#| "# let s = Circle(Point { x: 1f, y: 2f }, 3f);\n"
+#| "// As with typical function arguments, managed and owned pointers\n"
+#| "// are automatically converted to borrowed pointers\n"
 msgid ""
 "~~~\n"
 "# fn draw_circle(p: Point, f: f64) { }\n"
@@ -3835,22 +3067,48 @@ msgid ""
 "#     Rectangle(Point, Point)\n"
 "# }\n"
 "impl Shape {\n"
-"    fn draw_borrowed(&self) { ... }\n"
+"    fn draw_reference(&self) { ... }\n"
 "    fn draw_managed(@self) { ... }\n"
 "    fn draw_owned(~self) { ... }\n"
 "    fn draw_value(self) { ... }\n"
 "}\n"
 msgstr ""
+"~~~\n"
+"# fn draw_circle(p: Point, f: f64) { }\n"
+"# fn draw_rectangle(p: Point, p: Point) { }\n"
+"# struct Point { x: f64, y: f64 }\n"
+"# enum Shape {\n"
+"#     Circle(Point, f64),\n"
+"#     Rectangle(Point, Point)\n"
+"# }\n"
+"# impl Shape {\n"
+"#    fn draw_borrowed(&self) { ... }\n"
+"#    fn draw_managed(@self) { ... }\n"
+"#    fn draw_owned(~self) { ... }\n"
+"#    fn draw_value(self) { ... }\n"
+"# }\n"
+"# let s = Circle(Point { x: 1f, y: 2f }, 3f);\n"
+"// 関数の引数と同様、マネージドポインタと所有ポインタは、\n"
+"// 自動的に借用ポインタに変換される\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1669
-msgid "let s = Circle(Point { x: 1f, y: 2f }, 3f);"
+#: doc/tutorial.md:1890
+#, fuzzy
+#| msgid "let s = Circle(Point { x: 1f, y: 2f }, 3f); s.draw(); ~~~"
+msgid "let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);"
 msgstr ""
+"let s = Circle(Point { x: 1f, y: 2f }, 3f);\n"
+"s.draw();\n"
+"~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1675
+#: doc/tutorial.md:1896
+#, fuzzy
+#| msgid ""
+#| "(@s).draw_managed(); (~s).draw_owned(); (&s).draw_borrowed(); s."
+#| "draw_value(); ~~~"
 msgid ""
-"(@s).draw_managed(); (~s).draw_owned(); (&s).draw_borrowed(); s."
+"(@s).draw_managed(); (~s).draw_owned(); (&s).draw_reference(); s."
 "draw_value(); ~~~"
 msgstr ""
 "(@s).draw_managed();\n"
@@ -3860,17 +3118,39 @@ msgstr ""
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1679
+#: doc/tutorial.md:1900
+#, fuzzy
+#| msgid ""
+#| "Methods typically take a borrowed pointer self type, so the compiler will "
+#| "go to great lengths to convert a callee to a borrowed pointer."
 msgid ""
-"Methods typically take a borrowed pointer self type, so the compiler will go "
-"to great lengths to convert a callee to a borrowed pointer."
+"Methods typically take a reference self type, so the compiler will go to "
+"great lengths to convert a callee to a reference."
 msgstr ""
 "多くのメソッドは、借用ポインタの self 型を持つので、コンパイラは呼び出し先を"
 "借用ポインタに変換するためあらゆる手段を講じます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1697
-#, no-wrap
+#: doc/tutorial.md:1918
+#, fuzzy, no-wrap
+#| msgid ""
+#| "~~~\n"
+#| "# fn draw_circle(p: Point, f: f64) { }\n"
+#| "# fn draw_rectangle(p: Point, p: Point) { }\n"
+#| "# struct Point { x: f64, y: f64 }\n"
+#| "# enum Shape {\n"
+#| "#     Circle(Point, f64),\n"
+#| "#     Rectangle(Point, Point)\n"
+#| "# }\n"
+#| "# impl Shape {\n"
+#| "#    fn draw_borrowed(&self) { ... }\n"
+#| "#    fn draw_managed(@self) { ... }\n"
+#| "#    fn draw_owned(~self) { ... }\n"
+#| "#    fn draw_value(self) { ... }\n"
+#| "# }\n"
+#| "# let s = Circle(Point { x: 1f, y: 2f }, 3f);\n"
+#| "// As with typical function arguments, managed and owned pointers\n"
+#| "// are automatically converted to borrowed pointers\n"
 msgid ""
 "~~~\n"
 "# fn draw_circle(p: Point, f: f64) { }\n"
@@ -3881,14 +3161,14 @@ msgid ""
 "#     Rectangle(Point, Point)\n"
 "# }\n"
 "# impl Shape {\n"
-"#    fn draw_borrowed(&self) { ... }\n"
+"#    fn draw_reference(&self) { ... }\n"
 "#    fn draw_managed(@self) { ... }\n"
 "#    fn draw_owned(~self) { ... }\n"
 "#    fn draw_value(self) { ... }\n"
 "# }\n"
-"# let s = Circle(Point { x: 1f, y: 2f }, 3f);\n"
+"# let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);\n"
 "// As with typical function arguments, managed and owned pointers\n"
-"// are automatically converted to borrowed pointers\n"
+"// are automatically converted to references\n"
 msgstr ""
 "~~~\n"
 "# fn draw_circle(p: Point, f: f64) { }\n"
@@ -3909,38 +3189,48 @@ msgstr ""
 "// 自動的に借用ポインタに変換される\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1700
-msgid "(@s).draw_borrowed(); (~s).draw_borrowed();"
+#: doc/tutorial.md:1921
+#, fuzzy
+#| msgid "(@s).draw_borrowed(); (~s).draw_borrowed();"
+msgid "(@s).draw_reference(); (~s).draw_reference();"
 msgstr ""
 "(@s).draw_borrowed();\n"
 "(~s).draw_borrowed();"
 
 #. type: Plain text
-#: doc/tutorial.md:1704
+#: doc/tutorial.md:1925
+#, fuzzy
+#| msgid ""
+#| "// Unlike typical function arguments, the self value will // "
+#| "automatically be referenced ...  s.draw_borrowed();"
 msgid ""
 "// Unlike typical function arguments, the self value will // automatically "
-"be referenced ...  s.draw_borrowed();"
+"be referenced ...  s.draw_reference();"
 msgstr ""
 "// 関数の引数とは異なり、 self の値は自動的にリファレンスされたり、 ...\n"
 "s.draw_borrowed();"
 
 #. type: Plain text
-#: doc/tutorial.md:1707
-msgid "// ... and dereferenced (& &s).draw_borrowed();"
+#: doc/tutorial.md:1928
+#, fuzzy
+#| msgid "// ... and dereferenced (& &s).draw_borrowed();"
+msgid "// ... and dereferenced (& &s).draw_reference();"
 msgstr ""
 "// ... デリファレンスされたり、\n"
 "(& &s).draw_borrowed();"
 
 #. type: Plain text
-#: doc/tutorial.md:1711
-msgid "// ... and dereferenced and borrowed (&@~s).draw_borrowed(); ~~~"
+#: doc/tutorial.md:1932
+#, fuzzy
+#| msgid "// ... and dereferenced and borrowed (&@~s).draw_borrowed(); ~~~"
+msgid "// ... and dereferenced and borrowed (&@~s).draw_reference(); ~~~"
 msgstr ""
 "// ... デリファレンス後借用されたりします\n"
 "(&@~s).draw_borrowed();\n"
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1715
+#: doc/tutorial.md:1936
 msgid ""
 "Implementations may also define standalone (sometimes called \"static\")  "
 "methods. The absence of a `self` parameter distinguishes such methods.  "
@@ -3952,19 +3242,7 @@ msgstr ""
 "定義することが推奨されています。"
 
 #. type: Plain text
-#: doc/tutorial.md:1722
-#, no-wrap
-msgid ""
-"~~~~ {.xfail-test}\n"
-"impl Circle {\n"
-"    fn area(&self) -> f64 { ... }\n"
-"    fn new(area: f64) -> Circle { ... }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1724
+#: doc/tutorial.md:1945
 msgid ""
 "To call such a method, just prefix it with the type name and a double colon:"
 msgstr ""
@@ -3972,26 +3250,12 @@ msgstr ""
 "出せます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1733
-#, no-wrap
-msgid ""
-"~~~~\n"
-"use std::f64::consts::pi;\n"
-"struct Circle { radius: f64 }\n"
-"impl Circle {\n"
-"    fn new(area: f64) -> Circle { Circle { radius: (area / pi).sqrt() } }\n"
-"}\n"
-"let c = Circle::new(42.5);\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1735
+#: doc/tutorial.md:1956
 msgid "# Generics"
 msgstr "# ジェネリクス"
 
 #. type: Plain text
-#: doc/tutorial.md:1743
+#: doc/tutorial.md:1964
 msgid ""
 "Throughout this tutorial, we've been defining functions that act only on "
 "specific data types. With type parameters we can also define functions whose "
@@ -4007,22 +3271,7 @@ msgstr ""
 "`map` というジェネリック関数について考えます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1753
-#, no-wrap
-msgid ""
-"~~~~\n"
-"fn map<T, U>(vector: &[T], function: |v: &T| -> U) -> ~[U] {\n"
-"    let mut accumulator = ~[];\n"
-"    for element in vector.iter() {\n"
-"        accumulator.push(function(element));\n"
-"    }\n"
-"    return accumulator;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1758
+#: doc/tutorial.md:1979
 msgid ""
 "When defined with type parameters, as denoted by `<T, U>`, this function can "
 "be applied to any type of vector, as long as the type of `function`'s "
@@ -4033,7 +3282,7 @@ msgstr ""
 "任意の型のベクタを引数として渡すことが可能になります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1768
+#: doc/tutorial.md:1989
 msgid ""
 "Inside a generic function, the names of the type parameters (capitalized by "
 "convention) stand for opaque types. All you can do with instances of these "
@@ -4054,14 +3303,14 @@ msgstr ""
 "することで、関数の引数としてとることのできる型の範囲が広がります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1770
+#: doc/tutorial.md:1991
 msgid ""
 "Generic `type`, `struct`, and `enum` declarations follow the same pattern:"
 msgstr ""
 "ジェネリックな型、構造体、および列挙型の宣言は、同じパターンに従います。"
 
 #. type: Plain text
-#: doc/tutorial.md:1774
+#: doc/tutorial.md:1995
 msgid "~~~~ use std::hashmap::HashMap; type Set<T> = HashMap<T, ()>;"
 msgstr ""
 "~~~~\n"
@@ -4069,27 +3318,7 @@ msgstr ""
 "type Set<T> = HashMap<T, ()>;"
 
 #. type: Plain text
-#: doc/tutorial.md:1778
-#, no-wrap
-msgid ""
-"struct Stack<T> {\n"
-"    elements: ~[T]\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1784
-#, no-wrap
-msgid ""
-"enum Option<T> {\n"
-"    Some(T),\n"
-"    None\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1787
+#: doc/tutorial.md:2008
 msgid ""
 "These declarations can be instantiated to valid types like `Set<int>`, "
 "`Stack<int>`, and `Option<int>`."
@@ -4098,7 +3327,7 @@ msgstr ""
 "な型を生成することができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1793
+#: doc/tutorial.md:2014
 msgid ""
 "The last type in that example, `Option`, appears frequently in Rust code.  "
 "Because Rust does not have null pointers (except in unsafe code), we need "
@@ -4113,23 +3342,7 @@ msgstr ""
 "ることが一般的です。"
 
 #. type: Plain text
-#: doc/tutorial.md:1804
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# struct Point { x: f64, y: f64 }\n"
-"# enum Shape { Circle(Point, f64), Rectangle(Point, Point) }\n"
-"fn radius(shape: Shape) -> Option<f64> {\n"
-"    match shape {\n"
-"        Circle(_, radius) => Some(radius),\n"
-"        Rectangle(*)      => None\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1812
+#: doc/tutorial.md:2033
 msgid ""
 "The Rust compiler compiles generic functions very efficiently by "
 "*monomorphizing* them. *Monomorphization* is a fancy name for a simple idea: "
@@ -4146,21 +3359,34 @@ msgstr ""
 "の特性を持ちます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1814
+#: doc/tutorial.md:2035
 msgid "## Traits"
 msgstr "## トレイト"
 
 #. type: Plain text
-#: doc/tutorial.md:1824
-msgid ""
-"Within a generic function the operations available on generic types are very "
-"limited. After all, since the function doesn't know what types it is "
-"operating on, it can't safely modify or query their values. This is where "
-"_traits_ come into play. Traits are Rust's most powerful tool for writing "
-"polymorphic code. Java developers will see them as similar to Java "
+#: doc/tutorial.md:2047
+#, fuzzy
+#| msgid ""
+#| "Within a generic function the operations available on generic types are "
+#| "very limited. After all, since the function doesn't know what types it is "
+#| "operating on, it can't safely modify or query their values. This is where "
+#| "_traits_ come into play. Traits are Rust's most powerful tool for writing "
+#| "polymorphic code. Java developers will see them as similar to Java "
+#| "interfaces, and Haskellers will notice their similarities to type "
+#| "classes. Rust's traits are a form of *bounded polymorphism*: a trait is a "
+#| "way of limiting the set of possible types that a type parameter could "
+#| "refer to."
+msgid ""
+"Within a generic function -- that is, a function parameterized by a type "
+"parameter, say, `T` -- the operations we can do on arguments of type `T` are "
+"quite limited.  After all, since we don't know what type `T` will be "
+"instantiated with, we can't safely modify or query values of type `T`.  This "
+"is where _traits_ come into play. Traits are Rust's most powerful tool for "
+"writing polymorphic code. Java developers will see them as similar to Java "
 "interfaces, and Haskellers will notice their similarities to type classes. "
-"Rust's traits are a form of *bounded polymorphism*: a trait is a way of "
-"limiting the set of possible types that a type parameter could refer to."
+"Rust's traits give us a way to express *bounded polymorphism*: by limiting "
+"the set of possible types that a type parameter could refer to, they expand "
+"the number of operations we can safely perform on arguments of that type."
 msgstr ""
 "ジェネリック関数の内部では、ジェネリック型に対して非常に限られた操作しか行え"
 "ません。つまるところ、ジェネリック関数は操作の対象とする型が何なのか知らない"
@@ -4172,13 +3398,20 @@ msgstr ""
 "より、型パラメータが示す得る型の集合を限定することができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1832
+#: doc/tutorial.md:2054
+#, fuzzy
+#| msgid ""
+#| "As motivation, let us consider copying in Rust.  The `clone` method is "
+#| "not defined for all Rust types.  One reason is user-defined destructors: "
+#| "copying a type that has a destructor could result in the destructor "
+#| "running multiple times.  Therefore, types with destructors cannot be "
+#| "copied unless you explicitly implement `Clone` for them."
 msgid ""
-"As motivation, let us consider copying in Rust.  The `clone` method is not "
-"defined for all Rust types.  One reason is user-defined destructors: copying "
-"a type that has a destructor could result in the destructor running multiple "
-"times.  Therefore, types with destructors cannot be copied unless you "
-"explicitly implement `Clone` for them."
+"As motivation, let us consider copying of values in Rust.  The `clone` "
+"method is not defined for values of every type.  One reason is user-defined "
+"destructors: copying a value of a type that has a destructor could result in "
+"the destructor running multiple times.  Therefore, values of types that have "
+"destructors cannot be copied unless we explicitly implement `clone` for them."
 msgstr ""
 "トレイト導入の動機となる例として、Rust でのコピーについて考えます。`clone` メ"
 "ソッドはすべての Rust の型に対して定義されていません。定義されていない理由の"
@@ -4188,11 +3421,17 @@ msgstr ""
 "クタをもつ型をコピーすることはできません。"
 
 #. type: Plain text
-#: doc/tutorial.md:1837
+#: doc/tutorial.md:2060
+#, fuzzy
+#| msgid ""
+#| "This complicates handling of generic functions.  If you have a type "
+#| "parameter `T`, can you copy values of that type? In Rust, you can't, and "
+#| "if you try to run the following code the compiler will complain."
 msgid ""
-"This complicates handling of generic functions.  If you have a type "
-"parameter `T`, can you copy values of that type? In Rust, you can't, and if "
-"you try to run the following code the compiler will complain."
+"This complicates handling of generic functions.  If we have a function with "
+"a type parameter `T`, can we copy values of type `T` inside that function? "
+"In Rust, we can't, and if we try to run the following code the compiler will "
+"complain."
 msgstr ""
 "このことはジェネリック関数の扱い方を複雑にします。型パラメータ `T` が存在した"
 "として、この型の値をコピーすることができるでしょうか?Rust では、コピーするこ"
@@ -4200,7 +3439,7 @@ msgstr ""
 "う。"
 
 #. type: Plain text
-#: doc/tutorial.md:1844
+#: doc/tutorial.md:2067
 #, no-wrap
 msgid ""
 "~~~~ {.xfail-test}\n"
@@ -4218,19 +3457,25 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1851
+#: doc/tutorial.md:2073
+#, fuzzy
+#| msgid ""
+#| "However, we can tell the compiler that the `head` function is only for "
+#| "copyable types: that is, those that implement the `Clone` trait.  In that "
+#| "case, we can explicitly create a second copy of the value we are "
+#| "returning using the `clone` keyword:"
 msgid ""
 "However, we can tell the compiler that the `head` function is only for "
-"copyable types: that is, those that implement the `Clone` trait.  In that "
-"case, we can explicitly create a second copy of the value we are returning "
-"using the `clone` keyword:"
+"copyable types.  In Rust, copyable types are those that _implement the "
+"`Clone` trait_.  We can then explicitly create a second copy of the value we "
+"are returning by calling the `clone` method:"
 msgstr ""
 "`head` 関数はコピー可能な型、つまり `Clone` トレイトを実装している型だけを対"
 "象にしていることをコンパイラに教えることはできます。この場合、`clone` メソッ"
 "ドを使うことで、値のコピーを明示的に作成し、戻り値として返すことができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1858
+#: doc/tutorial.md:2080
 #, no-wrap
 msgid ""
 "~~~~\n"
@@ -4248,12 +3493,20 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1866
+#: doc/tutorial.md:2090
+#, fuzzy
+#| msgid ""
+#| "This says that we can call `head` on any type `T` as long as that type "
+#| "implements the `Clone` trait.  When instantiating a generic function, you "
+#| "can only instantiate it with types that implement the correct trait, so "
+#| "you could not apply `head` to a type that does not implement `Clone`."
 msgid ""
-"This says that we can call `head` on any type `T` as long as that type "
-"implements the `Clone` trait.  When instantiating a generic function, you "
-"can only instantiate it with types that implement the correct trait, so you "
-"could not apply `head` to a type that does not implement `Clone`."
+"The bounded type parameter `T: Clone` says that `head` can be called on an "
+"argument of type `&[T]` for any `T`, so long as there is an implementation "
+"of the `Clone` trait for `T`.  When instantiating a generic function, we can "
+"only instantiate it with types that implement the correct trait, so we could "
+"not apply `head` to a vector whose elements are of some type that does not "
+"implement `Clone`."
 msgstr ""
 "このことは、`Clone` トレイトを実装している任意の型 `T` について、 `head` 関数"
 "を呼び出すことができることを示しています。ジェネリック関数を実体化する場合、"
@@ -4261,9 +3514,14 @@ msgstr ""
 "レイトを実装していない型に対して `head` を呼び出すことはできません。"
 
 #. type: Plain text
-#: doc/tutorial.md:1871
+#: doc/tutorial.md:2095
+#, fuzzy
+#| msgid ""
+#| "While most traits can be defined and implemented by user code, two traits "
+#| "are automatically derived and implemented for all applicable types by the "
+#| "compiler, and may not be overridden:"
 msgid ""
-"While most traits can be defined and implemented by user code, two traits "
+"While most traits can be defined and implemented by user code, three traits "
 "are automatically derived and implemented for all applicable types by the "
 "compiler, and may not be overridden:"
 msgstr ""
@@ -4272,30 +3530,38 @@ msgstr ""
 "上書きすることはできません。"
 
 #. type: Plain text
-#: doc/tutorial.md:1875
-#, no-wrap
+#: doc/tutorial.md:2099
+#, fuzzy, no-wrap
+#| msgid ""
+#| "* `Send` - Sendable types.\n"
+#| "Types are sendable\n"
+#| "unless they contain managed boxes, managed closures, or borrowed pointers.\n"
 msgid ""
 "* `Send` - Sendable types.\n"
 "Types are sendable\n"
-"unless they contain managed boxes, managed closures, or borrowed pointers.\n"
+"unless they contain managed boxes, managed closures, or references.\n"
 msgstr ""
 "* `Send` - 送信可能な型。\n"
 "マネージドボックスやマネージドクロージャ、借用ポインタを含まない場合、型は送信可能である。"
 
 #. type: Plain text
-#: doc/tutorial.md:1880
-#, no-wrap
+#: doc/tutorial.md:2103
+#, fuzzy, no-wrap
+#| msgid ""
+#| "* `Freeze` - Constant (immutable) types.\n"
+#| "These are types that do not contain anything intrinsically mutable.\n"
+#| "Intrinsically mutable values include `@mut`\n"
+#| "and `Cell` in the standard library.\n"
 msgid ""
 "* `Freeze` - Constant (immutable) types.\n"
 "These are types that do not contain anything intrinsically mutable.\n"
-"Intrinsically mutable values include `@mut`\n"
-"and `Cell` in the standard library.\n"
+"Intrinsically mutable values include `Cell` in the standard library.\n"
 msgstr ""
 "* `Freeze` - 定数 (イミュータブル) 型。\n"
 "本質的に変更可能な値を含まない型のことです。本質的に変更可能な値には、`@mut` や標準ライブラリで定義されている `Cell` が含まれます。\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1883
+#: doc/tutorial.md:2112
 msgid ""
 "> ***Note:*** These two traits were referred to as 'kinds' in earlier > "
 "iterations of the language, and often still are."
@@ -4304,12 +3570,18 @@ msgstr ""
 "でもそう呼ばれる場合があります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1889
+#: doc/tutorial.md:2118
+#, fuzzy
+#| msgid ""
+#| "Additionally, the `Drop` trait is used to define destructors. This trait "
+#| "defines one method called `drop`, which is automatically called when a "
+#| "value of the type that implements this trait is destroyed, either because "
+#| "the value went out of scope or because the garbage collector reclaimed it."
 msgid ""
 "Additionally, the `Drop` trait is used to define destructors. This trait "
-"defines one method called `drop`, which is automatically called when a value "
-"of the type that implements this trait is destroyed, either because the "
-"value went out of scope or because the garbage collector reclaimed it."
+"provides one method called `drop`, which is automatically called when a "
+"value of the type that implements this trait is destroyed, either because "
+"the value went out of scope or because the garbage collector reclaimed it."
 msgstr ""
 "上記に加え、 `Drop` トレイトはデストラクタを定義するために使われます。このト"
 "レイトは `drop` というこのトレイトを実装した型が破壊されるタイミング(値がス"
@@ -4317,31 +3589,7 @@ msgstr ""
 "されるメソッドを1つ定義しています。"
 
 #. type: Plain text
-#: doc/tutorial.md:1894
-#, no-wrap
-msgid ""
-"~~~\n"
-"struct TimeBomb {\n"
-"    explosivity: uint\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1903
-#, no-wrap
-msgid ""
-"impl Drop for TimeBomb {\n"
-"    fn drop(&self) {\n"
-"        for _ in range(0, self.explosivity) {\n"
-"            println(\"blam!\");\n"
-"        }\n"
-"    }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1906
+#: doc/tutorial.md:2135
 msgid ""
 "It is illegal to call `drop` directly. Only code inserted by the compiler "
 "may call it."
@@ -4350,25 +3598,31 @@ msgstr ""
 "が `drop` を呼び出すことができます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1908
+#: doc/tutorial.md:2137
 msgid "## Declaring and implementing traits"
 msgstr "## トレイトの宣言と実装"
 
 #. type: Plain text
-#: doc/tutorial.md:1914
+#: doc/tutorial.md:2142
+#, fuzzy
+#| msgid ""
+#| "A trait consists of a set of methods without bodies, or may be empty, as "
+#| "is the case with `Send` and `Freeze`.  For example, we could declare the "
+#| "trait `Printable` for things that can be printed to the console, with a "
+#| "single method:"
 msgid ""
-"A trait consists of a set of methods without bodies, or may be empty, as is "
-"the case with `Send` and `Freeze`.  For example, we could declare the trait "
-"`Printable` for things that can be printed to the console, with a single "
-"method:"
+"At its simplest, a trait is a set of zero or more _method signatures_.  For "
+"example, we could declare the trait `Printable` for things that can be "
+"printed to the console, with a single method signature:"
 msgstr ""
 "トレイトはボディを持たないメソッドの集合から構成されるか、 `Send` や "
 "`Freeze` トレイトのように空の場合があります。例えば、コンソールに出力可能なも"
 "のを表しメソッドを1つもつ `Printable` トレイトは以下のように宣言できます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1920
-#, no-wrap
+#: doc/tutorial.md:2148
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
 msgid ""
 "~~~~\n"
 "trait Printable {\n"
@@ -4376,45 +3630,36 @@ msgid ""
 "}\n"
 "~~~~\n"
 msgstr ""
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1925
+#: doc/tutorial.md:2161
+#, fuzzy
+#| msgid ""
+#| "Traits may be implemented for specific types with [impls]. An impl that "
+#| "implements a trait includes the name of the trait at the start of the "
+#| "definition, as in the following impls of `Printable` for `int` and `~str`."
 msgid ""
-"Traits may be implemented for specific types with [impls]. An impl that "
-"implements a trait includes the name of the trait at the start of the "
-"definition, as in the following impls of `Printable` for `int` and `~str`."
+"Traits may be implemented for specific types with [impls]. An impl for a "
+"particular trait gives an implementation of the methods that trait "
+"provides.  For instance, the following impls of `Printable` for `int` and "
+"`~str` give implementations of the `print` method."
 msgstr ""
 "[impl][impls] により特定の型にトレイトを実装することができます。トレイトを実"
 "装する impl は、以下の `Printable` の `int` と `~str` に対する実装のように、"
 "定義の先頭にトレイトの名前を含みます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1927
+#: doc/tutorial.md:2163
 msgid "[impls]: #methods"
 msgstr "[impls]: #メソッド"
 
 #. type: Plain text
-#: doc/tutorial.md:1933
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# trait Printable { fn print(&self); }\n"
-"impl Printable for int {\n"
-"    fn print(&self) { println(fmt!(\"%d\", *self)) }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1937
-#, no-wrap
-msgid ""
-"impl Printable for ~str {\n"
-"    fn print(&self) { println(*self) }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:1941
+#: doc/tutorial.md:2177
 msgid "# 1.print(); # (~\"foo\").print(); ~~~~"
 msgstr ""
 "# 1.print();\n"
@@ -4422,12 +3667,16 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1946
+#: doc/tutorial.md:2180
+#, fuzzy
+#| msgid ""
+#| "Methods defined in an implementation of a trait may be called just like "
+#| "any other method, using dot notation, as in `1.print()`. Traits may "
+#| "themselves contain type parameters. A trait for generalized sequence "
+#| "types might look like the following:"
 msgid ""
-"Methods defined in an implementation of a trait may be called just like any "
-"other method, using dot notation, as in `1.print()`. Traits may themselves "
-"contain type parameters. A trait for generalized sequence types might look "
-"like the following:"
+"Methods defined in an impl for a trait may be called just like any other "
+"method, using dot notation, as in `1.print()`."
 msgstr ""
 "トレイトの実装により定義されたメソッドは他のメソッドと全く同じように、ドット"
 "記法を用いて `1.print()` のように呼び出せます。トレイト自体に型パラメータを持"
@@ -4435,27 +3684,35 @@ msgstr ""
 "されるでしょう。"
 
 #. type: Plain text
-#: doc/tutorial.md:1951
-#, no-wrap
-msgid ""
-"~~~~\n"
-"trait Seq<T> {\n"
-"    fn length(&self) -> uint;\n"
-"}\n"
+#: doc/tutorial.md:2182
+#, fuzzy
+#| msgid "## Deriving implementations for traits"
+msgid "## Default method implementations in trait definitions"
+msgstr "## トレイトの実装の導出"
+
+#. type: Plain text
+#: doc/tutorial.md:2202
+#, fuzzy
+#| msgid "# 1.print(); # (~\"foo\").print(); ~~~~"
+msgid "# true.print(); # 3.14159.print(); ~~~~"
 msgstr ""
+"# 1.print();\n"
+"# (~\"foo\").print();\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1956
-#, no-wrap
+#: doc/tutorial.md:2229
+#, fuzzy
+#| msgid "# 1.print(); # (~\"foo\").print(); ~~~~"
 msgid ""
-"impl<T> Seq<T> for ~[T] {\n"
-"    fn length(&self) -> uint { self.len() }\n"
-"}\n"
-"~~~~\n"
+"# 1.print(); # (~\"foo\").print(); # true.print(); # 3.14159.print(); ~~~~"
 msgstr ""
+"# 1.print();\n"
+"# (~\"foo\").print();\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:1963
+#: doc/tutorial.md:2260
 msgid ""
 "The implementation has to explicitly declare the type parameter that it "
 "binds, `T`, before using it to specify its trait type. Rust requires this "
@@ -4469,7 +3726,7 @@ msgstr ""
 "れるもの) は、型を定義するのではなく、型を **参照** します。"
 
 #. type: Plain text
-#: doc/tutorial.md:1968
+#: doc/tutorial.md:2265
 msgid ""
 "The type parameters bound by a trait are in scope in each of the method "
 "declarations. So, re-declaring the type parameter `T` as an explicit type "
@@ -4481,7 +3738,7 @@ msgstr ""
 "る明示的な型パラメータとして再宣言すると、コンパイル時エラーとなります。"
 
 #. type: Plain text
-#: doc/tutorial.md:1973
+#: doc/tutorial.md:2270
 msgid ""
 "Within a trait definition, `Self` is a special type that you can think of as "
 "a type parameter. An implementation of the trait for any given type `T` "
@@ -4493,7 +3750,7 @@ msgstr ""
 "えられます。以下のトレイトは等価性演算をサポートする型を意味します。"
 
 #. type: Plain text
-#: doc/tutorial.md:1980
+#: doc/tutorial.md:2277
 #, no-wrap
 msgid ""
 "~~~~\n"
@@ -4511,7 +3768,7 @@ msgstr ""
 "}\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1986
+#: doc/tutorial.md:2283
 #, no-wrap
 msgid ""
 "// In an impl, `self` refers just to the value of the receiver\n"
@@ -4527,7 +3784,7 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:1991
+#: doc/tutorial.md:2288
 msgid ""
 "Notice that in the trait definition, `equals` takes a second parameter of "
 "type `Self`.  In contrast, in the `impl`, `equals` takes a second parameter "
@@ -4538,7 +3795,7 @@ msgstr ""
 "シーバの名前としてのみ使用されます。"
 
 #. type: Plain text
-#: doc/tutorial.md:1996
+#: doc/tutorial.md:2293
 msgid ""
 "Just as in type implementations, traits can define standalone (static)  "
 "methods.  These methods are called by prefixing the method name with the "
@@ -4551,10 +3808,14 @@ msgstr ""
 "め、型推論を行います。"
 
 #. type: Plain text
-#: doc/tutorial.md:2002
+#: doc/tutorial.md:2299
+#, fuzzy
+#| msgid ""
+#| "~~~~ use std::f64::consts::pi; trait Shape { fn new(area: f64) -> Self; } "
+#| "struct Circle { radius: f64 } struct Square { length: f64 }"
 msgid ""
-"~~~~ use std::f64::consts::pi; trait Shape { fn new(area: f64) -> "
-"Self; } struct Circle { radius: f64 } struct Square { length: f64 }"
+"~~~~ use std::f64::consts::PI; trait Shape { fn new(area: f64) -> Self; } "
+"struct Circle { radius: f64 } struct Square { length: f64 }"
 msgstr ""
 "~~~~\n"
 "use std::f64::consts::pi;\n"
@@ -4563,19 +3824,7 @@ msgstr ""
 "struct Square { length: f64 }"
 
 #. type: Plain text
-#: doc/tutorial.md:2009
-#, no-wrap
-msgid ""
-"impl Shape for Circle {\n"
-"    fn new(area: f64) -> Circle { Circle { radius: (area / pi).sqrt() } }\n"
-"}\n"
-"impl Shape for Square {\n"
-"    fn new(area: f64) -> Square { Square { length: (area).sqrt() } }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2014
+#: doc/tutorial.md:2311
 msgid ""
 "let area = 42.5; let c: Circle = Shape::new(area); let s: Square = Shape::"
 "new(area); ~~~~"
@@ -4586,12 +3835,12 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2016
+#: doc/tutorial.md:2313
 msgid "## Bounded type parameters and static method dispatch"
 msgstr "## 境界型パラメータと静的メソッドディスパッチ"
 
 #. type: Plain text
-#: doc/tutorial.md:2021
+#: doc/tutorial.md:2318
 msgid ""
 "Traits give us a language for defining predicates on types, or abstract "
 "properties that types can have. We can use this language to define _bounds_ "
@@ -4603,21 +3852,7 @@ msgstr ""
 "なります。"
 
 #. type: Plain text
-#: doc/tutorial.md:2030
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# trait Printable { fn print(&self); }\n"
-"fn print_all<T: Printable>(printable_things: ~[T]) {\n"
-"    for thing in printable_things.iter() {\n"
-"        thing.print();\n"
-"    }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2036
+#: doc/tutorial.md:2333
 msgid ""
 "Declaring `T` as conforming to the `Printable` trait (as we earlier did with "
 "`Clone`) makes it possible to call methods from that trait on values of type "
@@ -4632,7 +3867,7 @@ msgstr ""
 "ル時エラーとなります。"
 
 #. type: Plain text
-#: doc/tutorial.md:2039
+#: doc/tutorial.md:2336
 msgid ""
 "Type parameters can have multiple bounds by separating them with `+`, as in "
 "this version of `print_all` that copies elements."
@@ -4641,24 +3876,7 @@ msgstr ""
 "`print_all` は、ベクタの要素をコピーするバージョンです。"
 
 #. type: Plain text
-#: doc/tutorial.md:2051
-#, no-wrap
-msgid ""
-"~~~\n"
-"# trait Printable { fn print(&self); }\n"
-"fn print_all<T: Printable + Clone>(printable_things: ~[T]) {\n"
-"    let mut i = 0;\n"
-"    while i < printable_things.len() {\n"
-"        let copy_of_thing = printable_things[i].clone();\n"
-"        copy_of_thing.print();\n"
-"        i += 1;\n"
-"    }\n"
-"}\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2055
+#: doc/tutorial.md:2352
 msgid ""
 "Method calls to bounded type parameters are _statically dispatched_, "
 "imposing no more overhead than normal function invocation, so are the "
@@ -4670,17 +3888,17 @@ msgstr ""
 "型パラメータが推奨されます。 "
 
 #. type: Plain text
-#: doc/tutorial.md:2057
+#: doc/tutorial.md:2354
 msgid "This usage of traits is similar to Haskell type classes."
 msgstr "トレイトのこのような使い方は、Haskell の型クラスと似ています。"
 
 #. type: Plain text
-#: doc/tutorial.md:2059
+#: doc/tutorial.md:2356
 msgid "## Trait objects and dynamic method dispatch"
 msgstr "## トレイトオブジェクトと動的メソッドディスパッチ"
 
 #. type: Plain text
-#: doc/tutorial.md:2063
+#: doc/tutorial.md:2360
 msgid ""
 "The above allows us to define functions that polymorphically act on values "
 "of a single unknown type that conforms to a given trait.  However, consider "
@@ -4690,7 +3908,7 @@ msgstr ""
 "フィックにふるまう関数を定義しました。ここでは、以下の関数について考えます。"
 
 #. type: Plain text
-#: doc/tutorial.md:2069
+#: doc/tutorial.md:2366
 msgid ""
 "~~~~ # type Circle = int; type Rectangle = int; # impl Drawable for int { fn "
 "draw(&self) {} } # fn new_circle() -> int { 1 } trait Drawable { fn "
@@ -4703,19 +3921,7 @@ msgstr ""
 "trait Drawable { fn draw(&self); }"
 
 #. type: Plain text
-#: doc/tutorial.md:2076
-#, no-wrap
-msgid ""
-"fn draw_all<T: Drawable>(shapes: ~[T]) {\n"
-"    for shape in shapes.iter() { shape.draw(); }\n"
-"}\n"
-"# let c: Circle = new_circle();\n"
-"# draw_all(~[c]);\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2082
+#: doc/tutorial.md:2379
 msgid ""
 "You can call that on an array of circles, or an array of rectangles "
 "(assuming those have suitable `Drawable` traits defined), but not on an "
@@ -4729,19 +3935,7 @@ msgstr ""
 "す。"
 
 #. type: Plain text
-#: doc/tutorial.md:2089
-#, no-wrap
-msgid ""
-"~~~~\n"
-"# trait Drawable { fn draw(&self); }\n"
-"fn draw_all(shapes: &[@Drawable]) {\n"
-"    for shape in shapes.iter() { shape.draw(); }\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2094
+#: doc/tutorial.md:2391
 msgid ""
 "In this example, there is no type parameter. Instead, the `@Drawable` type "
 "denotes any managed box value that implements the `Drawable` trait. To "
@@ -4753,7 +3947,7 @@ msgstr ""
 "うな値を作成するには、 `as` 演算子を使って値をオブジェクトへキャストします。"
 
 #. type: Plain text
-#: doc/tutorial.md:2101
+#: doc/tutorial.md:2398
 msgid ""
 "~~~~ # type Circle = int; type Rectangle = bool; # trait Drawable { fn "
 "draw(&self); } # fn new_circle() -> Circle { 1 } # fn new_rectangle() -> "
@@ -4767,7 +3961,7 @@ msgstr ""
 "# fn draw_all(shapes: &[@Drawable]) {}"
 
 #. type: Plain text
-#: doc/tutorial.md:2104
+#: doc/tutorial.md:2401
 msgid ""
 "impl Drawable for Circle { fn draw(&self) { ... } } impl Drawable for "
 "Rectangle { fn draw(&self) { ... } }"
@@ -4776,7 +3970,7 @@ msgstr ""
 "impl Drawable for Rectangle { fn draw(&self) { ... } }"
 
 #. type: Plain text
-#: doc/tutorial.md:2109
+#: doc/tutorial.md:2406
 msgid ""
 "let c: @Circle = @new_circle(); let r: @Rectangle = @new_rectangle(); "
 "draw_all([c as @Drawable, r as @Drawable]); ~~~~"
@@ -4787,7 +3981,7 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2117
+#: doc/tutorial.md:2414
 msgid ""
 "We omit the code for `new_circle` and `new_rectangle`; imagine that these "
 "just return `Circle`s and `Rectangle`s with a default size. Note that, like "
@@ -4804,7 +3998,7 @@ msgstr ""
 "`@Cicle` を `~Drawable` にキャストすることはできません。"
 
 #. type: Plain text
-#: doc/tutorial.md:2131
+#: doc/tutorial.md:2428
 msgid ""
 "~~~ # type Circle = int; type Rectangle = int; # trait Drawable { fn "
 "draw(&self); } # impl Drawable for int { fn draw(&self) {} } # fn "
@@ -4828,7 +4022,7 @@ msgstr ""
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2136
+#: doc/tutorial.md:2433
 msgid ""
 "Method calls to trait types are _dynamically dispatched_. Since the compiler "
 "doesn't know specifically which functions to call at compile time, it uses a "
@@ -4841,17 +4035,17 @@ msgstr ""
 "て、呼び出すメソッドの選択を実行時に行います。"
 
 #. type: Plain text
-#: doc/tutorial.md:2138
+#: doc/tutorial.md:2435
 msgid "This usage of traits is similar to Java interfaces."
 msgstr "トレイトのこのような使い方は、Java のインターフェースと似ています。"
 
 #. type: Plain text
-#: doc/tutorial.md:2140
+#: doc/tutorial.md:2461
 msgid "## Trait inheritance"
 msgstr "## トレイトの継承"
 
 #. type: Plain text
-#: doc/tutorial.md:2145
+#: doc/tutorial.md:2466
 msgid ""
 "We can write a trait declaration that _inherits_ from other traits, called "
 "_supertraits_.  Types that implement a trait must also implement its "
@@ -4864,7 +4058,7 @@ msgstr ""
 "のとして定義できます。"
 
 #. type: Plain text
-#: doc/tutorial.md:2150
+#: doc/tutorial.md:2471
 msgid ""
 "~~~~ trait Shape { fn area(&self) -> f64; } trait Circle : Shape { fn "
 "radius(&self) -> f64; } ~~~~"
@@ -4875,33 +4069,42 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2152
+#: doc/tutorial.md:2473
 msgid ""
 "Now, we can implement `Circle` on a type only if we also implement `Shape`."
 msgstr "`Circle` トレイトの実装は、 `Shape` を実装した型についてのみ行えます。"
 
 #. type: Plain text
-#: doc/tutorial.md:2167
-#, no-wrap
+#: doc/tutorial.md:2488
+#, fuzzy, no-wrap
+#| msgid "~~~ {.xfail-test} use std::f64::consts::pi; # trait Shape { fn area(&self) -> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } # struct Point { x: f64, y: f64 } # struct CircleStruct { center: Point, radius: f64 } # impl Circle for CircleStruct { fn radius(&self) -> f64 { (self.area() / pi).sqrt() } } # impl Shape for CircleStruct { fn area(&self) -> f64 { pi * square(self.radius) } }"
 msgid ""
 "~~~~\n"
-"use std::f64::consts::pi;\n"
+"use std::f64::consts::PI;\n"
 "# trait Shape { fn area(&self) -> f64; }\n"
 "# trait Circle : Shape { fn radius(&self) -> f64; }\n"
 "# struct Point { x: f64, y: f64 }\n"
 "# fn square(x: f64) -> f64 { x * x }\n"
 "struct CircleStruct { center: Point, radius: f64 }\n"
 "impl Circle for CircleStruct {\n"
-"    fn radius(&self) -> f64 { (self.area() / pi).sqrt() }\n"
+"    fn radius(&self) -> f64 { (self.area() / PI).sqrt() }\n"
 "}\n"
 "impl Shape for CircleStruct {\n"
-"    fn area(&self) -> f64 { pi * square(self.radius) }\n"
+"    fn area(&self) -> f64 { PI * square(self.radius) }\n"
 "}\n"
 "~~~~\n"
 msgstr ""
+"~~~ {.xfail-test}\n"
+"use std::f64::consts::pi;\n"
+"# trait Shape { fn area(&self) -> f64; }\n"
+"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
+"# struct Point { x: f64, y: f64 }\n"
+"# struct CircleStruct { center: Point, radius: f64 }\n"
+"# impl Circle for CircleStruct { fn radius(&self) -> f64 { (self.area() / pi).sqrt() } }\n"
+"# impl Shape for CircleStruct { fn area(&self) -> f64 { pi * square(self.radius) } }"
 
 #. type: Plain text
-#: doc/tutorial.md:2172
+#: doc/tutorial.md:2493
 msgid ""
 "Notice that methods of `Circle` can call methods on `Shape`, as our `radius` "
 "implementation calls the `area` method.  This is a silly way to compute the "
@@ -4914,14 +4117,55 @@ msgstr ""
 "ていますが、メソッド呼び出しの考え方は分かったでしょう。"
 
 #. type: Plain text
-#: doc/tutorial.md:2196
+#: doc/tutorial.md:2497
 msgid ""
-"~~~ {.xfail-test} use std::f64::consts::pi; # trait Shape { fn area(&self) "
-"-> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } # struct "
-"Point { x: f64, y: f64 } # struct CircleStruct { center: Point, radius: "
-"f64 } # impl Circle for CircleStruct { fn radius(&self) -> f64 { (self."
-"area() / pi).sqrt() } } # impl Shape for CircleStruct { fn area(&self) -> "
-"f64 { pi * square(self.radius) } }"
+"In type-parameterized functions, methods of the supertrait may be called on "
+"values of subtrait-bound type parameters.  Refering to the previous example "
+"of `trait Circle : Shape`:"
+msgstr ""
+"型パラメータを持つ関数では、サブトレイトの境界型パラメータの値によりスーパー"
+"トレイトのメソッドを呼び出すことになります。前の例の `trait Circle : Shape` "
+"を参照してください。"
+
+#. type: Plain text
+#: doc/tutorial.md:2506
+#, no-wrap
+msgid ""
+"~~~\n"
+"# trait Shape { fn area(&self) -> f64; }\n"
+"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
+"fn radius_times_area<T: Circle>(c: T) -> f64 {\n"
+"    // `c` is both a Circle and a Shape\n"
+"    c.radius() * c.area()\n"
+"}\n"
+"~~~\n"
+msgstr ""
+"~~~\n"
+"# trait Shape { fn area(&self) -> f64; }\n"
+"# trait Circle : Shape { fn radius(&self) -> f64; }\n"
+"fn radius_times_area<T: Circle>(c: T) -> f64 {\n"
+"    // `c` は Circle でもあり、Shape でもある\n"
+"    c.radius() * c.area()\n"
+"}\n"
+"~~~\n"
+
+#. type: Plain text
+#: doc/tutorial.md:2517
+#, fuzzy
+#| msgid ""
+#| "~~~ {.xfail-test} use std::f64::consts::pi; # trait Shape { fn "
+#| "area(&self) -> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } "
+#| "# struct Point { x: f64, y: f64 } # struct CircleStruct { center: Point, "
+#| "radius: f64 } # impl Circle for CircleStruct { fn radius(&self) -> f64 "
+#| "{ (self.area() / pi).sqrt() } } # impl Shape for CircleStruct { fn "
+#| "area(&self) -> f64 { pi * square(self.radius) } }"
+msgid ""
+"~~~ {.xfail-test} use std::f64::consts::PI; # trait Shape { fn area(&self) -"
+"> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } # struct Point "
+"{ x: f64, y: f64 } # struct CircleStruct { center: Point, radius: f64 } # "
+"impl Circle for CircleStruct { fn radius(&self) -> f64 { (self.area() / PI)."
+"sqrt() } } # impl Shape for CircleStruct { fn area(&self) -> f64 { PI * "
+"square(self.radius) } }"
 msgstr ""
 "~~~ {.xfail-test}\n"
 "use std::f64::consts::pi;\n"
@@ -4935,7 +4179,7 @@ msgstr ""
 "radius) } }"
 
 #. type: Plain text
-#: doc/tutorial.md:2201
+#: doc/tutorial.md:2522
 msgid ""
 "let concrete = @CircleStruct{center:Point{x:3f,y:4f},radius:5f}; let "
 "mycircle: @Circle = concrete as @Circle; let nonsense = mycircle.radius() * "
@@ -4947,19 +4191,19 @@ msgstr ""
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2203
+#: doc/tutorial.md:2524
 msgid "> ***Note:*** Trait inheritance does not actually work with objects yet"
 msgstr ""
 "> ***注意*** トレイトの継承は、実際にはまだオブジェクトに対しては動作しませ"
 "ん。"
 
 #. type: Plain text
-#: doc/tutorial.md:2205
+#: doc/tutorial.md:2526
 msgid "## Deriving implementations for traits"
 msgstr "## トレイトの実装の導出"
 
 #. type: Plain text
-#: doc/tutorial.md:2212
+#: doc/tutorial.md:2533
 msgid ""
 "A small number of traits in `std` and `extra` can have implementations that "
 "can be automatically derived. These instances are specified by placing the "
@@ -4975,7 +4219,7 @@ msgstr ""
 "に変換することが可能です。"
 
 #. type: Plain text
-#: doc/tutorial.md:2216
+#: doc/tutorial.md:2537
 msgid "~~~ #[deriving(Eq)] struct Circle { radius: f64 }"
 msgstr ""
 "~~~\n"
@@ -4983,7 +4227,7 @@ msgstr ""
 "struct Circle { radius: f64 }"
 
 #. type: Plain text
-#: doc/tutorial.md:2220
+#: doc/tutorial.md:2541
 msgid "#[deriving(Rand, ToStr)] enum ABC { A, B, C } ~~~"
 msgstr ""
 "#[deriving(Rand, ToStr)]\n"
@@ -4991,123 +4235,126 @@ msgstr ""
 "~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2224
+#: doc/tutorial.md:2545
+#, fuzzy
+#| msgid ""
+#| "The full list of derivable traits is `Eq`, `TotalEq`, `Ord`, `TotalOrd`, "
+#| "`Encodable` `Decodable`, `Clone`, `DeepClone`, `IterBytes`, `Rand`, "
+#| "`Zero`, and `ToStr`."
 msgid ""
 "The full list of derivable traits is `Eq`, `TotalEq`, `Ord`, `TotalOrd`, "
-"`Encodable` `Decodable`, `Clone`, `DeepClone`, `IterBytes`, `Rand`, `Zero`, "
-"and `ToStr`."
+"`Encodable` `Decodable`, `Clone`, `DeepClone`, `IterBytes`, `Rand`, "
+"`Default`, `Zero`, and `ToStr`."
 msgstr ""
 "実装を自動的に導出可能なトレイトは、 `Eq`, `TotalEq`, `Ord`, `TotalOrd`, "
 "`Encodable` `Decodable`, `Clone`, `DeepClone`, `IterBytes`, `Rand`, `Zero`, "
 "および `ToStr` です。."
 
 #. type: Plain text
-#: doc/tutorial.md:2226
-msgid "# Modules and crates"
+#: doc/tutorial.md:2547
+#, fuzzy
+#| msgid "# Modules and crates"
+msgid "# Crates and the module system"
 msgstr "# モジュールとクレート"
 
 #. type: Plain text
-#: doc/tutorial.md:2230
-msgid ""
-"The Rust namespace is arranged in a hierarchy of modules. Each source (.rs) "
-"file represents a single module and may in turn contain additional modules."
-msgstr ""
-"Rust の名前空間はモジュールの階層に配置されている。それぞれのソース (.rs) "
-"ファイルは単一のモジュールを表し、追加のモジュールを含んでいる場合もある。"
+#: doc/tutorial.md:2552
+msgid "## Crates"
+msgstr "## クレート"
 
 #. type: Plain text
-#: doc/tutorial.md:2236
-#, no-wrap
+#: doc/tutorial.md:2567
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
 msgid ""
 "~~~~\n"
-"mod farm {\n"
-"    pub fn chicken() -> &str { \"cluck cluck\" }\n"
-"    pub fn cow() -> &str { \"mooo\" }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2241
-#, no-wrap
-msgid ""
+"// main.rs\n"
 "fn main() {\n"
-"    println(farm::chicken());\n"
+"    println!(\"Hello world!\");\n"
 "}\n"
 "~~~~\n"
 msgstr ""
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2246
+#: doc/tutorial.md:2570
+#, fuzzy
+#| msgid ""
+#| "The unit of independent compilation in Rust is the crate: rustc compiles "
+#| "a single crate at a time, from which it produces either a library or an "
+#| "executable."
 msgid ""
-"The contents of modules can be imported into the current scope with the "
-"`use` keyword, optionally giving it an alias. `use` may appear at the "
-"beginning of crates, `mod`s, `fn`s, and other blocks."
+"A crate is also the unit of independent compilation in Rust: `rustc` always "
+"compiles a single crate at a time, from which it produces either a library "
+"or an executable."
 msgstr ""
-"でモジュールの内容は`use` キーワードにより現在のスコープにインポートすること"
-"ができます。必要に応じて別名を付けることもできます。`use` はクレートの先頭や "
-"`mod`, `fn` などのブロックの先頭に記述することができます。"
+"Rust の独立コンパイルの単位はクレートです。rustc は1度に1つのクレートをコンパ"
+"イルし、ライブラリか実行可能ファイルを生成します。"
 
 #. type: Plain text
-#: doc/tutorial.md:2252
-msgid ""
-"~~~ # mod farm { pub fn chicken() { } } # fn main() { // Bring `chicken` "
-"into scope use farm::chicken;"
-msgstr ""
-"~~~\n"
-"# mod farm { pub fn chicken() { } }\n"
-"# fn main() {\n"
-"// `chicken` を現在のスコープに持ち込む\n"
-"use farm::chicken;"
+#: doc/tutorial.md:2574
+#, fuzzy
+#| msgid "## The standard library"
+msgid "## The module hierarchy"
+msgstr "## 標準ライブラリ"
 
 #. type: Plain text
-#: doc/tutorial.md:2262
-#, no-wrap
+#: doc/tutorial.md:2600
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
 msgid ""
-"fn chicken_farmer() {\n"
-"    // The same, but name it `my_chicken`\n"
-"    use my_chicken = farm::chicken;\n"
-"    ...\n"
-"# my_chicken();\n"
+"fn main() {\n"
+"    println!(\"Hello farm!\");\n"
 "}\n"
-"# chicken();\n"
-"# }\n"
-"~~~\n"
+"~~~~\n"
 msgstr ""
-"fn chicken_farmer() {\n"
-"    // 同じことをするが、名前を `my_chicken` とする\n"
-"    use my_chicken = farm::chicken;\n"
-"    ...\n"
-"# my_chicken();\n"
-"}\n"
-"# chicken();\n"
-"# }\n"
-"~~~\n"
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
+
+#. type: Plain text
+#: doc/tutorial.md:2608
+#, fuzzy
+#| msgid "## Managed closures"
+msgid "## Paths and visibility"
+msgstr "## マネージドクロージャ"
 
 #. type: Plain text
-#: doc/tutorial.md:2269
+#: doc/tutorial.md:2620
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
 msgid ""
-"These farm animal functions have a new keyword, `pub`, attached to them. The "
-"`pub` keyword modifies an item's visibility, making it visible outside its "
-"containing module. An expression with `::`, like `farm::chicken`, can name "
-"an item outside of its containing module. Items, such as those declared with "
-"`fn`, `struct`, `enum`, `type`, or `static`, are module-private by default."
+"fn main() {\n"
+"    println!(\"Hello chicken!\");\n"
 msgstr ""
-"farm モジュールの動物の関数定義には、 `pub` という新しいキーワードが付けられ"
-"ています。`pub` キーワードは項目の可視性を変更し、項目を含んでいるモジュール"
-"の外側から見えるようにします。`farm::chicken` のような、 `::` を含む式は、式"
-"を含むモジュールの外側の項目を指定することができます。`fn` や `struct`, "
-"`enum`, `type`, `static` により宣言される項目の可視性は、デフォルトではモ"
-"ジュールプライベート (同一モジュール内からのみ参照可能)です。"
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2276
+#: doc/tutorial.md:2659
+#, fuzzy
+#| msgid ""
+#| "Visibility restrictions in Rust exist only at module boundaries. This is "
+#| "quite different from most object-oriented languages that also enforce "
+#| "restrictions on objects themselves. That's not to say that Rust doesn't "
+#| "support encapsulation: both struct fields and methods can be private. But "
+#| "this encapsulation is at the module level, not the struct level. Note "
+#| "that fields and methods are _public_ by default."
 msgid ""
 "Visibility restrictions in Rust exist only at module boundaries. This is "
 "quite different from most object-oriented languages that also enforce "
 "restrictions on objects themselves. That's not to say that Rust doesn't "
 "support encapsulation: both struct fields and methods can be private. But "
-"this encapsulation is at the module level, not the struct level. Note that "
-"fields and methods are _public_ by default."
+"this encapsulation is at the module level, not the struct level."
 msgstr ""
 "Rust での可視性の制約はモジュールの境界にのみ存在します。これは、オブジェクト"
 "自体にも可視性の制約を課すほとんどのオブジェクト指向言語とは全く異なっていま"
@@ -5118,302 +4365,85 @@ msgstr ""
 "してください。"
 
 #. type: Plain text
-#: doc/tutorial.md:2289
-#, no-wrap
-msgid ""
-"~~~\n"
-"pub mod farm {\n"
-"# pub type Chicken = int;\n"
-"# type Cow = int;\n"
-"# struct Human(int);\n"
-"# impl Human { fn rest(&self) { } }\n"
-"# pub fn make_me_a_farm() -> Farm { Farm { chickens: ~[], cows: ~[], farmer: Human(0) } }\n"
-"    pub struct Farm {\n"
-"        priv chickens: ~[Chicken],\n"
-"        priv cows: ~[Cow],\n"
-"        farmer: Human\n"
-"    }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2295
-#, no-wrap
-msgid ""
-"    impl Farm {\n"
-"        fn feed_chickens(&self) { ... }\n"
-"        fn feed_cows(&self) { ... }\n"
-"        pub fn add_chicken(&self, c: Chicken) { ... }\n"
-"    }\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2301
-#, no-wrap
-msgid ""
-"    pub fn feed_animals(farm: &Farm) {\n"
-"        farm.feed_chickens();\n"
-"        farm.feed_cows();\n"
-"    }\n"
-"}\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2311
-#, no-wrap
-msgid ""
-"fn main() {\n"
-"     let f = make_me_a_farm();\n"
-"     f.add_chicken(make_me_a_chicken());\n"
-"     farm::feed_animals(&f);\n"
-"     f.farmer.rest();\n"
-"}\n"
-"# fn make_me_a_farm() -> farm::Farm { farm::make_me_a_farm() }\n"
-"# fn make_me_a_chicken() -> farm::Chicken { 0 }\n"
-"~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2313
-msgid "## Crates"
-msgstr "## クレート"
-
-#. type: Plain text
-#: doc/tutorial.md:2317
-msgid ""
-"The unit of independent compilation in Rust is the crate: rustc compiles a "
-"single crate at a time, from which it produces either a library or an "
-"executable."
-msgstr ""
-"Rust の独立コンパイルの単位はクレートです。rustc は1度に1つのクレートをコンパ"
-"イルし、ライブラリか実行可能ファイルを生成します。"
-
-#. type: Plain text
-#: doc/tutorial.md:2322
-msgid ""
-"When compiling a single `.rs` source file, the file acts as the whole "
-"crate.  You can compile it with the `--lib` compiler switch to create a "
-"shared library, or without, provided that your file contains a `fn main` "
-"somewhere, to create an executable."
-msgstr ""
-"単一の `.rs` ファイルをコンパイルする場合、1つのファイルがクレート全体として"
-"振る舞います。`--lib` コンパイラスイッチを与えてコンパイルすることで、共有ラ"
-"イブラリを生成することができます。コンパイラスイッチを与えず、 `fn main` が"
-"ファイルのどこかに含まれていれば、実行可能ファイルを生成することができます。"
-
-#. type: Plain text
-#: doc/tutorial.md:2327
-msgid ""
-"Larger crates typically span multiple files and are, by convention, compiled "
-"from a source file with the `.rc` extension, called a *crate file*.  The "
-"crate file extension distinguishes source files that represent crates from "
-"those that do not, but otherwise source files and crate files are identical."
-msgstr ""
-"大きなクレートは普通複数のファイルから構成され、慣習的に、 `.rc` という拡張子"
-"をもつ、 **クレートファイル** と呼ばれるファイルからコンパイルされます。ク"
-"レートファイルの拡張子はクレートを表すソースファイルを他のものと区別するため"
-"だけのもので、それ以外の店でクレートファイルとソースファイルに違いはありませ"
-"ん。"
-
-#. type: Plain text
-#: doc/tutorial.md:2336
-msgid ""
-"A typical crate file declares attributes associated with the crate that may "
-"affect how the compiler processes the source.  Crate attributes specify "
-"metadata used for locating and linking crates, the type of crate (library or "
-"executable), and control warning and error behavior, among other things.  "
-"Crate files additionally declare the external crates they depend on as well "
-"as any modules loaded from other files."
-msgstr ""
-"典型的なクレートファイルでは、コンパイラのソースコード処理法に影響を与える、"
-"クレートに紐付けられた属性を宣言します。クレートの属性は、クレートの配置やリ"
-"ンクに使われたり、クレートの種類 (ライブラリか実行ファイルか) を指定したり、"
-"警告やエラーの挙動を制御したりするためのメタデータを指定します。クレートファ"
-"イルは、クレートが依存する外部のクレートや、他のファイルから読み込むモジュー"
-"ルについても宣言します。"
-
-#. type: Plain text
-#: doc/tutorial.md:2340
-msgid ""
-"~~~~ { .xfail-test } // Crate linkage metadata #[link(name = \"farm\", vers "
-"= \"2.5\", author = \"mjh\")];"
-msgstr ""
-"~~~~ { .xfail-test }\n"
-"// クレートのリンケージに関するメタデータ\n"
-"#[link(name = \"farm\", vers = \"2.5\", author = \"mjh\")];"
-
-#. type: Plain text
-#: doc/tutorial.md:2343
-msgid "// Make a library (\"bin\" is the default)  #[crate_type = \"lib\"];"
-msgstr ""
-"// ライブラリを作成する (\"bin\" がデフォルト値)\n"
-"#[crate_type = \"lib\"];"
-
-#. type: Plain text
-#: doc/tutorial.md:2346
-msgid "// Turn on a warning #[warn(non_camel_case_types)]"
-msgstr ""
-"// 警告を有効にする\n"
-"#[warn(non_camel_case_types)]"
-
-#. type: Plain text
-#: doc/tutorial.md:2349
-msgid "// Link to the standard library extern mod std;"
-msgstr ""
-"// 標準ライブラリをリンクする\n"
-"extern mod std;"
-
-#. type: Plain text
-#: doc/tutorial.md:2354
-msgid "// Load some modules from other files mod cow; mod chicken; mod horse;"
-msgstr ""
-"// 他のファイルからいくつかのモジュールを読み込む\n"
-"mod cow;\n"
-"mod chicken;\n"
-"mod horse;"
+#: doc/tutorial.md:2702
+#, fuzzy
+#| msgid "# Modules and crates"
+msgid "## Files and modules"
+msgstr "# モジュールとクレート"
 
 #. type: Plain text
-#: doc/tutorial.md:2359
-#, no-wrap
+#: doc/tutorial.md:2732
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
 msgid ""
 "fn main() {\n"
-"    ...\n"
+"    println!(\"Hello farm!\");\n"
+"    ::farm::cow();\n"
 "}\n"
 "~~~~\n"
 msgstr ""
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2366
-msgid ""
-"Compiling this file will cause `rustc` to look for files named `cow.rs`, "
-"`chicken.rs`, and `horse.rs` in the same directory as the `.rc` file, "
-"compile them all together, and, based on the presence of the `crate_type = "
-"\"lib\"` attribute, output a shared library or an executable. (If the line "
-"`#[crate_type = \"lib\"];` was omitted, `rustc` would create an executable.)"
-msgstr ""
-"このファイルをコンパイルすると、 `rustc` は `.rc` ファイルと同じディレクトリ"
-"の `cow.rs` と `chicken.rs`、 `horse.rs` を探し、すべてのファイルを同時にコン"
-"パイルし、`craete_type = \"lib\"` という属性の有無に応じて、共有ライブラリか"
-"実行可能ファイルを出力します。(`#[crate_type = \"lib\"];` の行が取り除かれば"
-"場合、 `rustc` は実行可能ファイルを生成します。)"
-
-#. type: Plain text
-#: doc/tutorial.md:2370
-msgid ""
-"The `#[link(...)]` attribute provides meta information about the module, "
-"which other crates can use to load the right module. More about that later."
+#: doc/tutorial.md:2791
+#, fuzzy
+#| msgid "~~~~ {.ignore} let foo = 10;"
+msgid "~~~ {.ignore} // src/main.rs mod plants; mod animals; ~~~"
 msgstr ""
-"`#[link(...)]` 属性は、モジュールに関するメタ情報を提供し、この情報により他の"
-"クレートは正しいモジュールをロードすることができます。あとで詳しく述べます。"
-
-#. type: Plain text
-#: doc/tutorial.md:2373
-msgid ""
-"To have a nested directory structure for your source files, you can nest "
-"mods:"
-msgstr ""
-"ソースファイルをネストしたディレクトリに配置する場合、`mod` をネストさせま"
-"す。"
-
-#. type: Plain text
-#: doc/tutorial.md:2380
-#, no-wrap
-msgid ""
 "~~~~ {.ignore}\n"
-"mod poultry {\n"
-"    mod chicken;\n"
-"    mod turkey;\n"
-"}\n"
-"~~~~\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2385
-msgid ""
-"The compiler will now look for `poultry/chicken.rs` and `poultry/turkey.rs`, "
-"and export their content in `poultry::chicken` and `poultry::turkey`. You "
-"can also provide a `poultry.rs` to add content to the `poultry` module "
-"itself."
-msgstr ""
-"コンパイラは `poultry/chicken.rs` と `poultry/turkey.rs` を読み込み、ファイル"
-"の内容を `poultry::chicken` と `poultry::turkey` としてエクスポートします。"
-"`poultry.rs` を作成することで、`poultry` モジュールの内容を追加することも可能"
-"です。"
-
-#. type: Plain text
-#: doc/tutorial.md:2387
-msgid "## Using other crates"
-msgstr "## 他のクレートの利用"
-
-#. type: Plain text
-#: doc/tutorial.md:2395
-msgid ""
-"The `extern mod` directive lets you use a crate (once it's been compiled "
-"into a library) from inside another crate. `extern mod` can appear at the "
-"top of a crate file or at the top of modules. It will cause the compiler to "
-"look in the library search path (which you can extend with the `-L` switch) "
-"for a compiled Rust library with the right name, then add a module with that "
-"crate's name into the local scope."
-msgstr ""
-"`extern mod` ディレクティブを使うと、あるクレートの中から、(ライブラリにコン"
-"パイルされている) 別のクレートを使用することができます。`extern mod` はク"
-"レートファイルの先頭かモジュールの先頭に記述することができます。コンパイラ"
-"は、対応する名前の Rust ライブラリをライブラリの検索パス (`-L` スイッチにより"
-"追加可能) から検索し、クレートと同じ名前のモジュールをローカルスコープに追加"
-"します。"
-
-#. type: Plain text
-#: doc/tutorial.md:2397
-msgid "For example, `extern mod std` links the [standard library]."
-msgstr ""
-"例えば、 `extern mod std` は [標準ライブラリ][standard library] をリンクしま"
-"す。"
-
-#. type: Plain text
-#: doc/tutorial.md:2399
-msgid "[standard library]: std/index.html"
-msgstr ""
+"let foo = 10;"
 
 #. type: Plain text
-#: doc/tutorial.md:2406
+#: doc/tutorial.md:2929
+#, fuzzy, no-wrap
+#| msgid "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
 msgid ""
-"When a comma-separated list of name/value pairs appears after `extern mod`, "
-"the compiler front-end matches these pairs against the attributes provided "
-"in the `link` attribute of the crate file. The front-end will only select "
-"this crate for use if the actual pairs match the declared attributes. You "
-"can provide a `name` value to override the name used to search for the crate."
+"fn main() {\n"
+"    println!(\"Hello farm!\");\n"
 msgstr ""
-"`extern mod` の後にカンマで区切られた名前と値のペアが記述された場合、コンパイ"
-"ラのフロントエンドはクレートファイルの `link` 属性によって指定された属性と比"
-"較します。フロントエンドは宣言された属性とペアが一致するクレートだけを選択"
-"し、利用します。`name` の値を設定することで、クレートの検索に使う名前を上書き"
-"することができます。"
+"~~~~ {.xfail-test}\n"
+"// main.rs\n"
+"extern mod world;\n"
+"fn main() { println(~\"hello \" + world::explore()); }\n"
+"~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2408
-msgid "Our example crate declared this set of `link` attributes:"
-msgstr ""
-"先ほどのクレートの例では、 `link` 属性は以下のように宣言されていました。"
+#: doc/tutorial.md:3004
+#, fuzzy
+#| msgid "# Dereferencing pointers"
+msgid "## Reexporting names"
+msgstr "# ポインタのデリファレンス"
 
 #. type: Plain text
-#: doc/tutorial.md:2412
-msgid "~~~~ #[link(name = \"farm\", vers = \"2.5\", author = \"mjh\")]; ~~~~"
-msgstr ""
-"~~~~\n"
-"#[link(name = \"farm\", vers = \"2.5\", author = \"mjh\")];\n"
-"~~~~"
+#: doc/tutorial.md:3039
+#, fuzzy
+#| msgid "## Using other crates"
+msgid "## Using libraries"
+msgstr "## 他のクレートの利用"
 
 #. type: Plain text
-#: doc/tutorial.md:2414
-msgid "Which you can then link with any (or all) of the following:"
+#: doc/tutorial.md:3080
+#, fuzzy
+#| msgid "~~~~ {.ignore} let foo = 10;"
+msgid "~~~ extern mod extra;"
 msgstr ""
-"以下のいずれか (またはすべて) の方法でクレートをリンクすることができます。"
+"~~~~ {.ignore}\n"
+"let foo = 10;"
 
 #. type: Plain text
-#: doc/tutorial.md:2420
+#: doc/tutorial.md:3144
+#, fuzzy
+#| msgid ""
+#| "~~~~ {.xfail-test} extern mod farm; extern mod my_farm (name = \"farm\", "
+#| "vers = \"2.5\"); extern mod my_auxiliary_farm (name = \"farm\", author = "
+#| "\"mjh\"); ~~~~"
 msgid ""
-"~~~~ {.xfail-test} extern mod farm; extern mod my_farm (name = \"farm\", "
-"vers = \"2.5\"); extern mod my_auxiliary_farm (name = \"farm\", author = "
-"\"mjh\"); ~~~~"
+"~~~~ {.xfail-test} extern mod farm; extern mod farm = \"farm#2.5\"; extern "
+"mod my_farm = \"farm\"; ~~~~"
 msgstr ""
 "~~~~ {.xfail-test}\n"
 "extern mod farm;\n"
@@ -5422,33 +4452,50 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2423
+#: doc/tutorial.md:3155
+#, fuzzy
+#| msgid "// Make a library (\"bin\" is the default)  #[crate_type = \"lib\"];"
 msgid ""
-"If any of the requested metadata do not match, then the crate will not be "
-"compiled successfully."
+"// This crate is a library (\"bin\" is the default)  #[crate_id = "
+"\"farm#2.5\"]; #[crate_type = \"lib\"];"
 msgstr ""
-"指定されたメタデータに一致するものが存在しない場合、クレートのコンパイルは失"
-"敗します。"
+"// ライブラリを作成する (\"bin\" がデフォルト値)\n"
+"#[crate_type = \"lib\"];"
 
 #. type: Plain text
-#: doc/tutorial.md:2425
+#: doc/tutorial.md:3160
+#, fuzzy
+#| msgid "// Turn on a warning #[warn(non_camel_case_types)]"
+msgid "// Turn on a warning #[warn(non_camel_case_types)] # fn farm() {} ~~~~"
+msgstr ""
+"// 警告を有効にする\n"
+"#[warn(non_camel_case_types)]"
+
+#. type: Plain text
+#: doc/tutorial.md:3167
 msgid "## A minimal example"
 msgstr "## 最小限の例"
 
 #. type: Plain text
-#: doc/tutorial.md:2428
-msgid ""
-"Now for something that you can actually compile yourself, we have these two "
-"files:"
+#: doc/tutorial.md:3169
+#, fuzzy
+#| msgid ""
+#| "Now for something that you can actually compile yourself, we have these "
+#| "two files:"
+msgid "Now for something that you can actually compile yourself."
 msgstr ""
 "あなた自身で実際にコンパイルが行える例として、以下の2つのファイルを例示しま"
 "す。"
 
 #. type: Plain text
-#: doc/tutorial.md:2434
+#: doc/tutorial.md:3179
+#, fuzzy
+#| msgid ""
+#| "~~~~ // world.rs #[link(name = \"world\", vers = \"1.0\")]; pub fn "
+#| "explore() -> &str { \"world\" } ~~~~"
 msgid ""
-"~~~~ // world.rs #[link(name = \"world\", vers = \"1.0\")]; pub fn explore() "
-"-> &str { \"world\" } ~~~~"
+"~~~~ // world.rs #[crate_id = \"world#0.42\"]; # extern mod extra; pub fn "
+"explore() -> &'static str { \"world\" } # fn main() {} ~~~~"
 msgstr ""
 "~~~~\n"
 "// world.rs\n"
@@ -5457,10 +4504,14 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2440
+#: doc/tutorial.md:3185
+#, fuzzy
+#| msgid ""
+#| "~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~"
+#| "\"hello \" + world::explore()); } ~~~~"
 msgid ""
-"~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println(~\"hello "
-"\" + world::explore()); } ~~~~"
+"~~~~ {.xfail-test} // main.rs extern mod world; fn main() { println!(\"hello "
+"{}\", world::explore()); } ~~~~"
 msgstr ""
 "~~~~ {.xfail-test}\n"
 "// main.rs\n"
@@ -5469,18 +4520,25 @@ msgstr ""
 "~~~~"
 
 #. type: Plain text
-#: doc/tutorial.md:2442
+#: doc/tutorial.md:3187
 msgid "Now compile and run like this (adjust to your platform if necessary):"
 msgstr ""
 "以下のようにコンパイルし、実行します (必要であれば、お使いのプラットフォーム"
 "に合わせて修正してください。)"
 
 #. type: Plain text
-#: doc/tutorial.md:2449
-#, no-wrap
+#: doc/tutorial.md:3194
+#, fuzzy, no-wrap
+#| msgid ""
+#| "~~~~ {.notrust}\n"
+#| "> rustc --lib world.rs  # compiles libworld-94839cbfe144198-1.0.so\n"
+#| "> rustc main.rs -L .    # compiles main\n"
+#| "> ./main\n"
+#| "\"hello world\"\n"
+#| "~~~~\n"
 msgid ""
 "~~~~ {.notrust}\n"
-"> rustc --lib world.rs  # compiles libworld-94839cbfe144198-1.0.so\n"
+"> rustc --lib world.rs  # compiles libworld-<HASH>-0.42.so\n"
 "> rustc main.rs -L .    # compiles main\n"
 "> ./main\n"
 "\"hello world\"\n"
@@ -5494,204 +4552,98 @@ msgstr ""
 "~~~~\n"
 
 #. type: Plain text
-#: doc/tutorial.md:2454
+#: doc/tutorial.md:3199
+#, fuzzy
+#| msgid ""
+#| "Notice that the library produced contains the version in the filename as "
+#| "well as an inscrutable string of alphanumerics. These are both part of "
+#| "Rust's library versioning scheme. The alphanumerics are a hash "
+#| "representing the crate metadata."
 msgid ""
-"Notice that the library produced contains the version in the filename as "
-"well as an inscrutable string of alphanumerics. These are both part of "
-"Rust's library versioning scheme. The alphanumerics are a hash representing "
-"the crate metadata."
+"Notice that the library produced contains the version in the file name as "
+"well as an inscrutable string of alphanumerics. As explained in the previous "
+"paragraph, these are both part of Rust's library versioning scheme. The "
+"alphanumerics are a hash representing the crates package ID."
 msgstr ""
 "生成されたライブラリのファイル名には、バージョン番号だけでなく謎めいた英数字"
 "が含まれていることに注意してください。これらは両方共 Rust のバージョン管理ス"
 "キームの一員です。英数字は、クレートのメタデータを表すハッシュ値です。"
 
 #. type: Plain text
-#: doc/tutorial.md:2456
-msgid "## The standard library"
+#: doc/tutorial.md:3201
+#, fuzzy
+#| msgid "## The standard library"
+msgid "## The standard library and the prelude"
 msgstr "## 標準ライブラリ"
 
 #. type: Plain text
-#: doc/tutorial.md:2461
-msgid ""
-"The Rust standard library provides runtime features required by the "
-"language, including the task scheduler and memory allocators, as well as "
-"library support for Rust built-in types, platform abstractions, and other "
-"commonly used features."
-msgstr ""
-"Rust の標準ライブラリは、タスクスケジューラやメモリアロケータを含む、言語自体"
-"が必要とするランタイム機能を提供するだけでなく、Rust の組み込み型や、プラット"
-"フォームの抽象化、その他一般的によく利用される機能ををサポートするライブラリ"
-"を含んでいます。"
-
-#. type: Plain text
-#: doc/tutorial.md:2472
-msgid ""
-"[`std`] includes modules corresponding to each of the integer types, each of "
-"the floating point types, the [`bool`] type, [tuples], [characters], "
-"[strings], [vectors], [managed boxes], [owned boxes], and unsafe and "
-"borrowed [pointers].  Additionally, `std` provides some pervasive types "
-"([`option`] and [`result`]), [task] creation and [communication] primitives, "
-"platform abstractions ([`os`] and [`path`]), basic I/O abstractions "
-"([`io`]), [containers] like [`hashmap`], common traits ([`kinds`], [`ops`], "
-"[`cmp`], [`num`], [`to_str`], [`clone`]), and complete bindings to the C "
-"standard library ([`libc`])."
-msgstr ""
-"[`std`] は整数型や浮動小数点型、[`bool`] 型、[タプル][tuples]、[文字]"
-"[characters]、[文字列][strings]、[ベクタ][vectors]、[マネージドボックス]"
-"[managed boxes]、[所有ボックス][owned boxes]、unsafe または借用 [ポインタ]"
-"[pointers] に対応するモジュールを含んでいます。さらに、 `std` は、いくつかの"
-"よく使われる型 ([`option`] と [`result`])や、 [タスク][task] 生成と[通信]"
-"[communication] のためのプリミティブ、プラットフォームの抽象化 ([`os`] と "
-"[`path`])、基本的な I/O の抽象化 ([`io`]), [`hashmap`] などの [コンテナ]"
-"[containers]、共通的に使われるトレイト ([`kinds`], [`ops`], [`cmp`], "
-"[`num`], [`to_str`], [`clone`])、C 標準ライブラリ ([`libc`]) への完全なバイン"
-"ディングを提供します。"
-
-#. type: Plain text
-#: doc/tutorial.md:2474
-msgid "### Standard Library injection and the Rust prelude"
-msgstr "### 標準ライブラリの注入と Rust の prelude"
-
-#. type: Plain text
-#: doc/tutorial.md:2477
-msgid ""
-"`std` is imported at the topmost level of every crate by default, as if the "
-"first line of each crate was"
-msgstr ""
-"`std` は、すべてのクレートの先頭以下の行か書かれているかのように、デフォルト"
-"でクレートの最上位のレベルにインポートされます。"
-
-#. type: Plain text
-#: doc/tutorial.md:2479
-#, no-wrap
-msgid "    extern mod std;\n"
+#: doc/tutorial.md:3213
+#, fuzzy
+#| msgid "~~~~ {.ignore} let foo = 10;"
+msgid "~~~ {.ignore} extern mod std; ~~~"
 msgstr ""
+"~~~~ {.ignore}\n"
+"let foo = 10;"
 
 #. type: Plain text
-#: doc/tutorial.md:2483
-msgid ""
-"This means that the contents of std can be accessed from from any context "
-"with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, "
-"etc."
+#: doc/tutorial.md:3219
+#, fuzzy
+#| msgid "~~~~ {.ignore} let foo = 10;"
+msgid "~~~ {.ignore} use std::prelude::*; ~~~"
 msgstr ""
-"これは、 std の内容には `std::` というパスプレフィックスを付けることで、任意"
-"のコンテキストから `use std::vec`. `use std::task::spawn` のようにアクセスで"
-"きることを意味します。"
+"~~~~ {.ignore}\n"
+"let foo = 10;"
 
 #. type: Plain text
-#: doc/tutorial.md:2488
-msgid ""
-"Additionally, `std` contains a `prelude` module that reexports many of the "
-"most common standard modules, types and traits. The contents of the prelude "
-"are imported into every *module* by default.  Implicitly, all modules behave "
-"as if they contained the following prologue:"
-msgstr ""
-"さらに、 `std` は `prelude` という、最も共通的なモジュールや型、トレイトを再"
-"エクスポートするモジュールを含んでいます。prelude の内容は、デフォルトですべ"
-"ての **モジュール** にインポートされます。すべてのモジュールは、以下の文言を"
-"モジュール先頭に暗黙的に含んでいるように動作します。"
+#: doc/tutorial.md:3260
+#, fuzzy
+#| msgid "## The standard library"
+msgid "## The extra library"
+msgstr "## 標準ライブラリ"
 
 #. type: Plain text
-#: doc/tutorial.md:2490
-#, no-wrap
-msgid "    use std::prelude::*;\n"
-msgstr ""
-
-#. type: Plain text
-#: doc/tutorial.md:2516
-msgid ""
-"[`std`]: std/index.html [`bool`]: std/bool.html [tuples]: std/tuple.html "
-"[characters]: std/char.html [strings]: std/str.html [vectors]: std/vec.html "
-"[managed boxes]: std/managed.html [owned boxes]: std/owned.html [pointers]: "
-"std/ptr.html [`option`]: std/option.html [`result`]: std/result.html [task]: "
-"std/task.html [communication]: std/comm.html [`os`]: std/os.html [`path`]: "
-"std/path.html [`io`]: std/io.html [containers]: std/container.html "
-"[`hashmap`]: std/hashmap.html [`kinds`]: std/kinds.html [`ops`]: std/ops."
-"html [`cmp`]: std/cmp.html [`num`]: std/num.html [`to_str`]: std/to_str.html "
-"[`clone`]: std/clone.html [`libc`]: std/libc.html"
-msgstr ""
-"[`std`]: std/index.html\n"
-"[`bool`]: std/bool.html\n"
-"[tuples]: std/tuple.html\n"
-"[characters]: std/char.html\n"
-"[strings]: std/str.html\n"
-"[vectors]: std/vec.html\n"
-"[managed boxes]: std/managed.html\n"
-"[owned boxes]: std/owned.html\n"
-"[pointers]: std/ptr.html\n"
-"[`option`]: std/option.html\n"
-"[`result`]: std/result.html\n"
-"[task]: std/task.html\n"
-"[communication]: std/comm.html\n"
-"[`os`]: std/os.html\n"
-"[`path`]: std/path.html\n"
-"[`io`]: std/io.html\n"
-"[containers]: std/container.html\n"
-"[`hashmap`]: std/hashmap.html\n"
-"[`kinds`]: std/kinds.html\n"
-"[`ops`]: std/ops.html\n"
-"[`cmp`]: std/cmp.html\n"
-"[`num`]: std/num.html\n"
-"[`to_str`]: std/to_str.html\n"
-"[`clone`]: std/clone.html\n"
-"[`libc`]: std/libc.html"
-
-#. type: Plain text
-#: doc/tutorial.md:2518
+#: doc/tutorial.md:3271
 msgid "# What next?"
 msgstr "# 次のステップは?"
 
 #. type: Plain text
-#: doc/tutorial.md:2521
+#: doc/tutorial.md:3274
+#, fuzzy
+#| msgid ""
+#| "Now that you know the essentials, check out any of the additional "
+#| "tutorials on individual topics."
 msgid ""
-"Now that you know the essentials, check out any of the additional tutorials "
-"on individual topics."
+"Now that you know the essentials, check out any of the additional guides on "
+"individual topics."
 msgstr ""
 "Rust の本質的な部分に関する説明は以上です。個々のトピックにおける追加のチュー"
 "トリアルもチェックしてみてください。"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:2527
-msgid "[Borrowed pointers][borrow]"
-msgstr "[借用ポインタ][borrow]"
-
-#. type: Bullet: '* '
-#: doc/tutorial.md:2527
+#: doc/tutorial.md:3286
 msgid "[Tasks and communication][tasks]"
 msgstr "[タスクと通信][tasks]"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:2527
+#: doc/tutorial.md:3286
 msgid "[Macros][macros]"
 msgstr "[マクロ][macros]"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:2527
+#: doc/tutorial.md:3286
 msgid "[The foreign function interface][ffi]"
 msgstr "[他言語間インターフェース (foreign function inferface)][ffi]"
 
 #. type: Bullet: '* '
-#: doc/tutorial.md:2527
-msgid "[Containers and iterators](tutorial-container.html)"
+#: doc/tutorial.md:3286
+#, fuzzy
+#| msgid "[Containers and iterators](tutorial-container.html)"
+msgid "[Containers and iterators][container]"
 msgstr "[コンテナとイテレータ](tutorial-container.html)"
 
-#. type: Plain text
-#: doc/tutorial.md:2529
-msgid "There is further documentation on the [wiki]."
-msgstr "[wiki] にもドキュメントがあります。"
-
-#. type: Plain text
-#: doc/tutorial.md:2534
-msgid ""
-"[borrow]: tutorial-borrowed-ptr.html [tasks]: tutorial-tasks.html [macros]: "
-"tutorial-macros.html [ffi]: tutorial-ffi.html"
-msgstr ""
-"[borrow]: tutorial-borrowed-ptr.html\n"
-"[tasks]: tutorial-tasks.html\n"
-"[macros]: tutorial-macros.html\n"
-"[ffi]: tutorial-ffi.html"
-
-#. type: Plain text
-#: doc/tutorial.md:2536
-msgid "[wiki]: https://github.com/mozilla/rust/wiki/Docs"
-msgstr ""
+#. type: Bullet: '* '
+#: doc/tutorial.md:3286
+#, fuzzy
+#| msgid "% The Rust Language Tutorial"
+msgid "[The Rust Runtime][runtime]"
+msgstr "% Rust 言語チュートリアル"
index ac0f64acca9ad03b26cd4665963b294de3c15f79..ad93964d6aa870ae017bd051729e1cbb1a91d0ad 100644 (file)
@@ -806,7 +806,9 @@ path_glob : ident [ "::" path_glob ] ?
 
 A _use declaration_ creates one or more local name bindings synonymous
 with some other [path](#paths).
-Usually a `use` declaration is used to shorten the path required to refer to a module item.
+Usually a `use` declaration is used to shorten the path required to refer to a
+module item. These declarations may appear at the top of [modules](#modules) and
+[blocks](#blocks).
 
 *Note*: Unlike in many languages,
 `use` declarations in Rust do *not* declare linkage dependency with external crates.
@@ -2318,14 +2320,24 @@ let base = Point3d {x: 1, y: 2, z: 3};
 Point3d {y: 0, z: 10, .. base};
 ~~~~
 
-### Record expressions
+### Block expressions
 
 ~~~~ {.ebnf .gram}
-rec_expr : '{' ident ':' expr
-               [ ',' ident ':' expr ] *
-               [ ".." expr ] '}'
+block_expr : '{' [ view_item ] *
+                 [ stmt ';' | item ] *
+                 [ expr ] '}'
 ~~~~
 
+A _block expression_ is similar to a module in terms of the declarations that
+are possible. Each block conceptually introduces a new namespace scope. View
+items can bring new names into scopes and declared items are in scope for only
+the block itself.
+
+A block will execute each statement sequentially, and then execute the
+expression (if given). If the final expression is omitted, the type and return
+value of the block are `()`, but if it is provided, the type and return value
+of the block are that of the expression itself.
+
 ### Method-call expressions
 
 ~~~~ {.ebnf .gram}
index 3641590662fef54506ccea12fdc1deb68bc4a07a..5de12f90bcf73dcc457e8ffe0f8c54985b188abd 100644 (file)
@@ -149,7 +149,7 @@ $$(HLIB$(2)_H_$(4))/$(CFG_LIBNATIVE_$(4)): \
 $$(HBIN$(2)_H_$(4))/:
        mkdir -p $$@
 
-ifneq ($(LIBDIR_RELATIVE),bin)
+ifneq ($(CFG_LIBDIR_RELATIVE),bin)
 $$(HLIB$(2)_H_$(4))/:
        mkdir -p $$@
 endif
index f8d0c624de5e78d6d027b1696adc3249e4d3430a..13c4ae5e860f73f92cdeede7882c170a5885910b 100644 (file)
@@ -28,7 +28,7 @@ LLVM_STAMP_$(1) = $$(CFG_LLVM_BUILD_DIR_$(1))/llvm-auto-clean-stamp
 
 $$(LLVM_CONFIG_$(1)): $$(LLVM_DEPS) $$(LLVM_STAMP_$(1))
        @$$(call E, make: llvm)
-       $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) $$(CFG_LLVM_BUILD_ENV_$(1))
+       $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) $$(CFG_LLVM_BUILD_ENV_$(1)) ONLY_TOOLS="$$(LLVM_TOOLS)"
        $$(Q)touch $$(LLVM_CONFIG_$(1))
 endif
 
index d7d94b7eedfa5885cf56cdd4be101855abd39b6f..57eb67c8efbed6584acd69f899830162c712b1b3 100644 (file)
@@ -103,13 +103,13 @@ endif
 ifdef CFG_WINDOWSY_$(1)
   CFG_TESTLIB_$(1)=$$(CFG_BUILD_DIR)$$(2)/$$(strip \
    $$(if $$(findstring stage0,$$(1)), \
-       stage0/$$(LIBDIR_RELATIVE), \
+       stage0/$$(CFG_LIBDIR_RELATIVE), \
       $$(if $$(findstring stage1,$$(1)), \
-           stage1/$$(LIBDIR_RELATIVE), \
+           stage1/$$(CFG_LIBDIR_RELATIVE), \
           $$(if $$(findstring stage2,$$(1)), \
-               stage2/$$(LIBDIR_RELATIVE), \
+               stage2/$$(CFG_LIBDIR_RELATIVE), \
                $$(if $$(findstring stage3,$$(1)), \
-                    stage3/$$(LIBDIR_RELATIVE), \
+                    stage3/$$(CFG_LIBDIR_RELATIVE), \
                )))))/$$(CFG_RUSTLIBDIR)/$$(CFG_BUILD)/lib
   CFG_RUN_TEST_$(1)=$$(call CFG_RUN_$(1),$$(call CFG_TESTLIB_$(1),$$(1),$$(3)),$$(1))
 endif
index 3caddb2af4954f855bd1c9da108ce298a44bc71d..9aedbacb3daa19b9e2977eee1037cf7c5855986d 100644 (file)
@@ -90,10 +90,14 @@ pub fn is_test_ignored(config: &config, testfile: &Path) -> bool {
     fn xfail_target(config: &config) -> ~str {
         ~"xfail-" + util::get_os(config.target)
     }
+    fn xfail_stage(config: &config) -> ~str {
+        ~"xfail-" + config.stage_id.split('-').next().unwrap()
+    }
 
     let val = iter_header(testfile, |ln| {
         if parse_name_directive(ln, "xfail-test") { false }
         else if parse_name_directive(ln, xfail_target(config)) { false }
+        else if parse_name_directive(ln, xfail_stage(config)) { false }
         else if config.mode == common::mode_pretty &&
             parse_name_directive(ln, "xfail-pretty") { false }
         else { true }
index 272bbc6fbbd6c05b964dcaefb7d804fb65202bdd..de777c997299d1d8b82efba5d91d573a9ed5655a 100755 (executable)
@@ -7,13 +7,20 @@ if __name__ == '__main__':
     summaries = []
     def summarise(fname):
         summary = {}
-        fd = open(fname)
-        for line in fd:
-            status, test = line.strip().split(' ', 1)
-            if not summary.has_key(status):
-                summary[status] = []
-            summary[status].append(test)
-        summaries.append((fname, summary))
+        with open(fname) as fd:
+            for line in fd:
+                splitline = line.strip().split(' ')
+                if len(splitline) == 1:
+                    continue
+                status = splitline[0]
+                test = splitline[-1]
+                # track bench runs
+                if splitline[1] == 'ns/iter':
+                    status = 'bench'
+                if not summary.has_key(status):
+                    summary[status] = []
+                summary[status].append(test)
+            summaries.append((fname, summary))
     def count(t):
         return sum(map(lambda (f, s): len(s.get(t, [])), summaries))
     logfiles = sys.argv[1:]
@@ -21,8 +28,9 @@ if __name__ == '__main__':
     ok = count('ok')
     failed = count('failed')
     ignored = count('ignored')
-    print "summary of %d test runs: %d passed; %d failed; %d ignored" % \
-            (len(logfiles), ok, failed, ignored)
+    measured = count('bench')
+    print "summary of %d test runs: %d passed; %d failed; %d ignored; %d measured" % \
+            (len(logfiles), ok, failed, ignored, measured)
     print ""
     if failed > 0:
         print "failed tests:"
index 65e7cd061496dfd10afceb7b08c35d4e4625f4f2..fdb978ae7e12b2cf25f9ee539a4cd60be2dbb657 100644 (file)
@@ -83,8 +83,7 @@ syn keyword rustTrait OrdIterator MutableDoubleEndedIterator ExactSize
 syn keyword rustTrait Times
 
 syn keyword rustTrait Algebraic Trigonometric Exponential Hyperbolic
-syn keyword rustTrait Bitwise BitCount Bounded
-syn keyword rustTrait Integer Fractional Real RealExt
+syn keyword rustTrait Bitwise Bounded Integer Fractional Real RealExt
 syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul
 syn keyword rustTrait Orderable Signed Unsigned Round
 syn keyword rustTrait Primitive Int Float ToStrRadix ToPrimitive FromPrimitive
index 28a6ba36a710c360c1568febe4e7e3f2fbd5ad74..6f9475d091ad65436dd263244775491f2263ca08 100644 (file)
@@ -154,7 +154,25 @@ fn to_base64(&self, config: Config) -> ~str {
 pub trait FromBase64 {
     /// Converts the value of `self`, interpreted as base64 encoded data, into
     /// an owned vector of bytes, returning the vector.
-    fn from_base64(&self) -> Result<~[u8], ~str>;
+    fn from_base64(&self) -> Result<~[u8], FromBase64Error>;
+}
+
+/// Errors that can occur when decoding a base64 encoded string
+pub enum FromBase64Error {
+    /// The input contained a character not part of the base64 format
+    InvalidBase64Character(char, uint),
+    /// The input had an invalid length
+    InvalidBase64Length,
+}
+
+impl ToStr for FromBase64Error {
+    fn to_str(&self) -> ~str {
+        match *self {
+            InvalidBase64Character(ch, idx) =>
+                format!("Invalid character '{}' at position {}", ch, idx),
+            InvalidBase64Length => ~"Invalid length",
+        }
+    }
 }
 
 impl<'a> FromBase64 for &'a str {
@@ -188,7 +206,7 @@ impl<'a> FromBase64 for &'a str {
      * }
      * ```
      */
-    fn from_base64(&self) -> Result<~[u8], ~str> {
+    fn from_base64(&self) -> Result<~[u8], FromBase64Error> {
         let mut r = ~[];
         let mut buf: u32 = 0;
         let mut modulus = 0;
@@ -205,8 +223,7 @@ fn from_base64(&self) -> Result<~[u8], ~str> {
                 '/'|'_' => buf |= 0x3F,
                 '\r'|'\n' => continue,
                 '=' => break,
-                _ => return Err(format!("Invalid character '{}' at position {}",
-                                     self.char_at(idx), idx))
+                _ => return Err(InvalidBase64Character(self.char_at(idx), idx)),
             }
 
             buf <<= 6;
@@ -221,8 +238,7 @@ fn from_base64(&self) -> Result<~[u8], ~str> {
 
         for (idx, byte) in it {
             if (byte as char) != '=' {
-                return Err(format!("Invalid character '{}' at position {}",
-                                self.char_at(idx), idx));
+                return Err(InvalidBase64Character(self.char_at(idx), idx));
             }
         }
 
@@ -235,7 +251,7 @@ fn from_base64(&self) -> Result<~[u8], ~str> {
                 r.push((buf >> 8 ) as u8);
             }
             0 => (),
-            _ => return Err(~"Invalid Base64 length")
+            _ => return Err(InvalidBase64Length),
         }
 
         Ok(r)
index 52b5bedb7ea4917cdf111d84d097ef5c285f1e52..748289080532cd5e343afbade51403824db5f997 100644 (file)
@@ -16,6 +16,8 @@
 
 #[allow(missing_doc)];
 
+use std::comm;
+
 /// An extension of `pipes::stream` that allows both sending and receiving.
 pub struct DuplexStream<T, U> {
     priv chan: Chan<T>,
@@ -40,7 +42,7 @@ pub fn try_send(&self, x: T) -> bool {
     pub fn recv(&self) -> U {
         self.port.recv()
     }
-    pub fn try_recv(&self) -> Option<U> {
+    pub fn try_recv(&self) -> comm::TryRecvResult<U> {
         self.port.try_recv()
     }
     pub fn recv_opt(&self) -> Option<U> {
@@ -77,11 +79,11 @@ pub fn recv_opt(&self) -> Option<T> {
         })
     }
 
-    pub fn try_recv(&self) -> Option<T> {
-        self.duplex_stream.try_recv().map(|val| {
-            self.duplex_stream.try_send(());
-            val
-        })
+    pub fn try_recv(&self) -> comm::TryRecvResult<T> {
+        match self.duplex_stream.try_recv() {
+            comm::Data(t) => { self.duplex_stream.try_send(()); comm::Data(t) }
+            state => state,
+        }
     }
 }
 
@@ -125,9 +127,9 @@ fn recv_a_lot() {
         // Rendezvous streams should be able to handle any number of messages being sent
         let (port, chan) = rendezvous();
         do spawn {
-            1000000.times(|| { chan.send(()) })
+            10000.times(|| { chan.send(()) })
         }
-        1000000.times(|| { port.recv() })
+        10000.times(|| { port.recv() })
     }
 
     #[test]
index 9feaa32732460d6f56bfa619b290fc58100c45fe..84d4584751d013bf91a047f1e6a188db898e7a69 100644 (file)
@@ -90,7 +90,7 @@ pub mod reader {
 
     // ebml reading
 
-    struct Res {
+    pub struct Res {
         val: uint,
         next: uint
     }
@@ -130,32 +130,40 @@ pub fn vuint_at(data: &[u8], start: uint) -> Res {
             return vuint_at_slow(data, start);
         }
 
+        // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/
+        // The Element IDs are parsed by reading a big endian u32 positioned at data[start].
+        // Using the four most significant bits of the u32 we lookup in the table below how the
+        // element ID should be derived from it.
+        //
+        // The table stores tuples (shift, mask) where shift is the number the u32 should be right
+        // shifted with and mask is the value the right shifted value should be masked with.
+        // If for example the most significant bit is set this means it's a class A ID and the u32
+        // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at
+        // index 0x8 - 0xF (four bit numbers where the most significant bit is set).
+        //
+        // By storing the number of shifts and masks in a table instead of checking in order if
+        // the most significant bit is set, the second most significant bit is set etc. we can
+        // replace up to three "and+branch" with a single table lookup which gives us a measured
+        // speedup of around 2x on x86_64.
+        static SHIFT_MASK_TABLE: [(u32, u32), ..16] = [
+            (0, 0x0), (0, 0x0fffffff),
+            (8, 0x1fffff), (8, 0x1fffff),
+            (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
+            (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
+            (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
+        ];
+
         unsafe {
             let (ptr, _): (*u8, uint) = transmute(data);
             let ptr = offset(ptr, start as int);
             let ptr: *i32 = transmute(ptr);
-            let val = from_be32(*ptr);
-            let val: u32 = transmute(val);
-            if (val & 0x80000000) != 0 {
-                Res {
-                    val: ((val >> 24) & 0x7f) as uint,
-                    next: start + 1
-                }
-            } else if (val & 0x40000000) != 0 {
-                Res {
-                    val: ((val >> 16) & 0x3fff) as uint,
-                    next: start + 2
-                }
-            } else if (val & 0x20000000) != 0 {
-                Res {
-                    val: ((val >> 8) & 0x1fffff) as uint,
-                    next: start + 3
-                }
-            } else {
-                Res {
-                    val: (val & 0x0fffffff) as uint,
-                    next: start + 4
-                }
+            let val = from_be32(*ptr) as u32;
+
+            let i = (val >> 28u) as uint;
+            let (shift, mask) = SHIFT_MASK_TABLE[i];
+            Res {
+                val: ((val >> shift) & mask) as uint,
+                next: start + (((32 - shift) >> 3) as uint)
             }
         }
     }
@@ -938,6 +946,54 @@ mod tests {
     use std::io::MemWriter;
     use std::option::{None, Option, Some};
 
+    #[test]
+    fn test_vuint_at() {
+        let data = [
+            0x80,
+            0xff,
+            0x40, 0x00,
+            0x7f, 0xff,
+            0x20, 0x00, 0x00,
+            0x3f, 0xff, 0xff,
+            0x10, 0x00, 0x00, 0x00,
+            0x1f, 0xff, 0xff, 0xff
+        ];
+
+        let mut res: reader::Res;
+
+        // Class A
+        res = reader::vuint_at(data, 0);
+        assert_eq!(res.val, 0);
+        assert_eq!(res.next, 1);
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, (1 << 7) - 1);
+        assert_eq!(res.next, 2);
+
+        // Class B
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, 0);
+        assert_eq!(res.next, 4);
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, (1 << 14) - 1);
+        assert_eq!(res.next, 6);
+
+        // Class C
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, 0);
+        assert_eq!(res.next, 9);
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, (1 << 21) - 1);
+        assert_eq!(res.next, 12);
+
+        // Class D
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, 0);
+        assert_eq!(res.next, 16);
+        res = reader::vuint_at(data, res.next);
+        assert_eq!(res.val, (1 << 28) - 1);
+        assert_eq!(res.next, 20);
+    }
+
     #[test]
     fn test_option_int() {
         fn test_v(v: Option<int>) {
index 6fd42f74a767ff7bf22414e22f6d86025cdc6c17..e04617780758be3f796dfd6d7e96a28c40637369 100644 (file)
@@ -13,6 +13,8 @@
 //! This module defines a container which uses an efficient bit mask
 //! representation to hold C-like enum variants.
 
+use std::num::Bitwise;
+
 #[deriving(Clone, Eq, IterBytes, ToStr, Encodable, Decodable)]
 /// A specialized Set implementation to use enum types.
 pub struct EnumSet<E> {
index 380476dc4bca07695ee745917cb5cab29cd3eb15..e5fcd39667de0a37d4487a993970d3e1847e9e1b 100644 (file)
@@ -53,7 +53,25 @@ fn to_hex(&self) -> ~str {
 pub trait FromHex {
     /// Converts the value of `self`, interpreted as hexadecimal encoded data,
     /// into an owned vector of bytes, returning the vector.
-    fn from_hex(&self) -> Result<~[u8], ~str>;
+    fn from_hex(&self) -> Result<~[u8], FromHexError>;
+}
+
+/// Errors that can occur when decoding a hex encoded string
+pub enum FromHexError {
+    /// The input contained a character not part of the hex format
+    InvalidHexCharacter(char, uint),
+    /// The input had a invalid length
+    InvalidHexLength,
+}
+
+impl ToStr for FromHexError {
+    fn to_str(&self) -> ~str {
+        match *self {
+            InvalidHexCharacter(ch, idx) =>
+                format!("Invalid character '{}' at position {}", ch, idx),
+            InvalidHexLength => ~"Invalid input length",
+        }
+    }
 }
 
 impl<'a> FromHex for &'a str {
@@ -83,7 +101,7 @@ impl<'a> FromHex for &'a str {
      * }
      * ```
      */
-    fn from_hex(&self) -> Result<~[u8], ~str> {
+    fn from_hex(&self) -> Result<~[u8], FromHexError> {
         // This may be an overestimate if there is any whitespace
         let mut b = vec::with_capacity(self.len() / 2);
         let mut modulus = 0;
@@ -100,8 +118,7 @@ fn from_hex(&self) -> Result<~[u8], ~str> {
                     buf >>= 4;
                     continue
                 }
-                _ => return Err(format!("Invalid character '{}' at position {}",
-                                        self.char_at(idx), idx))
+                _ => return Err(InvalidHexCharacter(self.char_at(idx), idx)),
             }
 
             modulus += 1;
@@ -113,7 +130,7 @@ fn from_hex(&self) -> Result<~[u8], ~str> {
 
         match modulus {
             0 => Ok(b),
-            _ => Err(~"Invalid input length")
+            _ => Err(InvalidHexLength),
         }
     }
 }
index fc0cc0451757773246bad0729deda1e684aaf45c..b3dda5cbc21c66985e55f0bc2e9cdb164badcf47 100644 (file)
@@ -20,7 +20,8 @@
 
 */
 
-#[crate_id = "extra#0.10-pre"];
+// NOTE: upgrade to 0.10-pre after the next snapshot
+#[crate_id = "extra#0.9"];
 #[comment = "Rust extras"];
 #[license = "MIT/ASL2"];
 #[crate_type = "rlib"];
index ed731298b52a53fd4c441c57c532ef209f1ddadc..8f491e836b8f2a0e9a6463751f674f5157de3d51 100644 (file)
@@ -22,7 +22,7 @@
 use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
 use std::num;
 use std::num::{Zero, One, ToStrRadix, FromStrRadix, Orderable};
-use std::num::{ToPrimitive, FromPrimitive};
+use std::num::{Bitwise, ToPrimitive, FromPrimitive};
 use std::rand::Rng;
 use std::str;
 use std::uint;
index 12566ac85515f314bbda1d12ade07812368e530f..044e5e9e5098937c203a317433e309d82e28c797 100644 (file)
@@ -19,6 +19,7 @@
 
 
 use std::borrow;
+use std::comm;
 use std::unstable::sync::Exclusive;
 use std::sync::arc::UnsafeArc;
 use std::sync::atomics;
@@ -49,7 +50,7 @@ fn new() -> WaitQueue {
     // Signals one live task from the queue.
     fn signal(&self) -> bool {
         match self.head.try_recv() {
-            Some(ch) => {
+            comm::Data(ch) => {
                 // Send a wakeup signal. If the waiter was killed, its port will
                 // have closed. Keep trying until we get a live task.
                 if ch.try_send_deferred(()) {
@@ -58,7 +59,7 @@ fn signal(&self) -> bool {
                     self.signal()
                 }
             }
-            None => false
+            _ => false
         }
     }
 
@@ -66,12 +67,12 @@ fn broadcast(&self) -> uint {
         let mut count = 0;
         loop {
             match self.head.try_recv() {
-                None => break,
-                Some(ch) => {
+                comm::Data(ch) => {
                     if ch.try_send_deferred(()) {
                         count += 1;
                     }
                 }
+                _ => break
             }
         }
         count
index 84f67743a3acc87a43e32b17cfd0740e8cddb881..ed3dcb5d7379b1f051b98d256a5ed7e0f94e6712 100644 (file)
@@ -474,7 +474,7 @@ pub fn write_log(&mut self, test: &TestDesc, result: &TestResult) {
         match self.log_out {
             None => (),
             Some(ref mut o) => {
-                let s = format!("{} {}", match *result {
+                let s = format!("{} {}\n", match *result {
                         TrOk => ~"ok",
                         TrFailed => ~"failed",
                         TrIgnored => ~"ignored",
index 9c9edc3ddd924a9e4c4688c7fb928fbe225175dd..222155d9ab356096ce3f7460fc92d04f22b25891 100644 (file)
@@ -1458,7 +1458,7 @@ fn test_timespec_eq_ord() {
     }
 
     #[test]
-    #[ignore(cfg(android))] // FIXME #10958
+    #[ignore(cfg(target_os = "android"))] // FIXME #10958
     fn run_tests() {
         // The tests race on tzset. So instead of having many independent
         // tests, we will just call the functions now.
index 56dc3204da86e1ad391db59f7e35c2eb812c675f..12def918bc9e248ef4acaee0a667a9e14c6cc4f0 100644 (file)
@@ -13,7 +13,6 @@
 #[macro_escape];
 
 use std::fmt;
-use std::libc;
 
 // Indicates whether we should perform expensive sanity checks, including rtassert!
 // XXX: Once the runtime matures remove the `true` below to turn off rtassert, etc.
@@ -124,6 +123,7 @@ pub fn abort(msg: &str) -> ! {
     abort();
 
     fn abort() -> ! {
-        unsafe { libc::abort() }
+        use std::unstable::intrinsics;
+        unsafe { intrinsics::abort() }
     }
 }
index b0b88e4be7936033f630b5126313f4a2e7861319..1ae4d07af18ec9d5ba4782301834f8220906298c 100644 (file)
@@ -958,6 +958,7 @@ fn new_sched_rng() -> XorShiftRng {
 
 #[cfg(test)]
 mod test {
+    use std::comm;
     use std::task::TaskOpts;
     use std::rt::Runtime;
     use std::rt::task::Task;
@@ -1376,7 +1377,7 @@ fn dont_starve_1() {
             // This task should not be able to starve the sender;
             // The sender should get stolen to another thread.
             do spawn {
-                while port.try_recv().is_none() { }
+                while port.try_recv() != comm::Data(()) { }
             }
 
             chan.send(());
@@ -1393,7 +1394,7 @@ fn dont_starve_2() {
             // This task should not be able to starve the other task.
             // The sends should eventually yield.
             do spawn {
-                while port.try_recv().is_none() {
+                while port.try_recv() != comm::Data(()) {
                     chan2.send(());
                 }
             }
diff --git a/src/libnative/bookeeping.rs b/src/libnative/bookeeping.rs
deleted file mode 100644 (file)
index ca40c1a..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! 1:1 Task bookeeping
-//!
-//! This module keeps track of the number of running 1:1 tasks so that entry
-//! points with libnative know when it's possible to exit the program (once all
-//! tasks have exited).
-//!
-//! The green counterpart for this is bookeeping on sched pools.
-
-use std::sync::atomics;
-use std::unstable::mutex::{Mutex, MUTEX_INIT};
-
-static mut TASK_COUNT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
-static mut TASK_LOCK: Mutex = MUTEX_INIT;
-
-pub fn increment() {
-    unsafe { TASK_COUNT.fetch_add(1, atomics::SeqCst); }
-}
-
-pub fn decrement() {
-    unsafe {
-        if TASK_COUNT.fetch_sub(1, atomics::SeqCst) == 1 {
-            TASK_LOCK.lock();
-            TASK_LOCK.signal();
-            TASK_LOCK.unlock();
-        }
-    }
-}
-
-/// Waits for all other native tasks in the system to exit. This is only used by
-/// the entry points of native programs
-pub fn wait_for_other_tasks() {
-    unsafe {
-        TASK_LOCK.lock();
-        while TASK_COUNT.load(atomics::SeqCst) > 0 {
-            TASK_LOCK.wait();
-        }
-        TASK_LOCK.unlock();
-    }
-}
diff --git a/src/libnative/bookkeeping.rs b/src/libnative/bookkeeping.rs
new file mode 100644 (file)
index 0000000..6c5f555
--- /dev/null
@@ -0,0 +1,49 @@
+// 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.
+
+//! 1:1 Task bookkeeping
+//!
+//! This module keeps track of the number of running 1:1 tasks so that entry
+//! points with libnative know when it's possible to exit the program (once all
+//! tasks have exited).
+//!
+//! The green counterpart for this is bookkeeping on sched pools.
+
+use std::sync::atomics;
+use std::unstable::mutex::{Mutex, MUTEX_INIT};
+
+static mut TASK_COUNT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
+static mut TASK_LOCK: Mutex = MUTEX_INIT;
+
+pub fn increment() {
+    unsafe { TASK_COUNT.fetch_add(1, atomics::SeqCst); }
+}
+
+pub fn decrement() {
+    unsafe {
+        if TASK_COUNT.fetch_sub(1, atomics::SeqCst) == 1 {
+            TASK_LOCK.lock();
+            TASK_LOCK.signal();
+            TASK_LOCK.unlock();
+        }
+    }
+}
+
+/// Waits for all other native tasks in the system to exit. This is only used by
+/// the entry points of native programs
+pub fn wait_for_other_tasks() {
+    unsafe {
+        TASK_LOCK.lock();
+        while TASK_COUNT.load(atomics::SeqCst) > 0 {
+            TASK_LOCK.wait();
+        }
+        TASK_LOCK.unlock();
+    }
+}
index 91c5e5051786a86e2614cbc67ba2bdff54c5df71..f69ad8fc1aa7ff111883d61379d3277541bcd4c3 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -29,7 +29,7 @@
 use std::os;
 use std::rt;
 
-mod bookeeping;
+mod bookkeeping;
 pub mod io;
 pub mod task;
 
 #[cfg(unix, not(android))]
 static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
 
-
-// XXX: this should not exist here
-#[cfg(stage0, nativestart)]
-#[lang = "start"]
-pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
-    use std::cast;
-    use std::task;
-
-    do start(argc, argv) {
-        // Instead of invoking main directly on this thread, invoke it on
-        // another spawned thread that we are guaranteed to know the size of the
-        // stack of. Currently, we do not have a method of figuring out the size
-        // of the main thread's stack, so for stack overflow detection to work
-        // we must spawn the task in a subtask which we know the stack size of.
-        let main: extern "Rust" fn() = unsafe { cast::transmute(main) };
-        let mut task = task::task();
-        task.name("<main>");
-        match do task.try { main() } {
-            Ok(()) => { os::set_exit_status(0); }
-            Err(..) => { os::set_exit_status(rt::DEFAULT_ERROR_CODE); }
-        }
-    }
-}
-
 /// Executes the given procedure after initializing the runtime with the given
 /// argc/argv.
 ///
@@ -99,6 +75,6 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
 /// number of arguments.
 pub fn run(main: proc()) -> int {
     main();
-    bookeeping::wait_for_other_tasks();
+    bookkeeping::wait_for_other_tasks();
     os::get_exit_status()
 }
index e827b495852a45d0db153b92160cb275f5656289..d2f68c4ef681dd0b56ad9690921b6494135b7029 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -27,7 +27,7 @@
 
 use io;
 use task;
-use bookeeping;
+use bookkeeping;
 
 /// Creates a new Task which is ready to execute as a 1:1 task.
 pub fn new(stack_bounds: (uint, uint)) -> ~Task {
@@ -82,7 +82,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
     // Note that this increment must happen *before* the spawn in order to
     // guarantee that if this task exits it will always end up waiting for the
     // spawned task to exit.
-    bookeeping::increment();
+    bookkeeping::increment();
 
     // Spawning a new OS thread guarantees that __morestack will never get
     // triggered, but we must manually set up the actual stack bounds once this
@@ -104,7 +104,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
         let mut task = task;
         task.put_runtime(ops as ~rt::Runtime);
         task.run(|| { f.take_unwrap()() });
-        bookeeping::decrement();
+        bookkeeping::decrement();
     })
 }
 
index 945ee645414b7e8ae6bd26f119feb3b69c674115..8f639a5e499f1d2f2440c0d95da1faec67969734 100644 (file)
@@ -45,9 +45,8 @@
 pub static tydesc_field_take_glue: uint = 2u;
 pub static tydesc_field_drop_glue: uint = 3u;
 pub static tydesc_field_visit_glue: uint = 4u;
-pub static tydesc_field_borrow_offset: uint = 5u;
-pub static tydesc_field_name_offset: uint = 6u;
-pub static n_tydesc_fields: uint = 7u;
+pub static tydesc_field_name_offset: uint = 5u;
+pub static n_tydesc_fields: uint = 6u;
 
 // The two halves of a closure: code and environment.
 pub static fn_field_code: uint = 0u;
index ffb9cce033ed71deaca769e86304e69a73df967e..65195468ed3c055244cdb531dedc5bbabd804940 100644 (file)
@@ -1166,7 +1166,7 @@ fn add_local_native_libraries(args: &mut ~[~str], sess: Session) {
 fn add_upstream_rust_crates(args: &mut ~[~str], sess: Session,
                             dylib: bool, tmpdir: &Path) {
     // Converts a library file-stem into a cc -l argument
-    fn unlib(config: @session::config, stem: &str) -> ~str {
+    fn unlib(config: @session::Config, stem: &str) -> ~str {
         if stem.starts_with("lib") &&
             config.os != abi::OsWin32 {
             stem.slice(3, stem.len()).to_owned()
index ecf4dd95cecb4b8ff8e4546511f753290631c2ab..43ecbccfd79dcf09fee86a83b3190b3b42c633e0 100644 (file)
@@ -39,7 +39,7 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> ~[~str] {
 
     debug!("preparing the RPATH!");
 
-    let sysroot = sess.filesearch.sysroot();
+    let sysroot = sess.filesearch.sysroot;
     let output = out_filename;
     let libs = sess.cstore.get_used_crates(cstore::RequireDynamic);
     let libs = libs.move_iter().filter_map(|(_, l)| l.map(|p| p.clone())).collect();
@@ -55,7 +55,7 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> ~[~str] {
 
 fn get_sysroot_absolute_rt_lib(sess: session::Session) -> Path {
     let r = filesearch::relative_target_lib_path(sess.opts.target_triple);
-    let mut p = sess.filesearch.sysroot().join(&r);
+    let mut p = sess.filesearch.sysroot.join(&r);
     p.push(os::dll_filename("rustrt"));
     p
 }
index 058728f26a018633ee120e91c8a406cbbac966c8..9555a706f0874b3c7588c0be8fdb4b052165107c 100644 (file)
@@ -20,6 +20,7 @@
 use metadata::common::LinkMeta;
 use metadata::{creader, filesearch};
 use metadata::cstore::CStore;
+use metadata::creader::Loader;
 use metadata;
 use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable};
 use middle;
@@ -41,6 +42,7 @@
 use syntax::attr::{AttrMetaMethods};
 use syntax::codemap;
 use syntax::diagnostic;
+use syntax::ext::base::CrateLoader;
 use syntax::parse;
 use syntax::parse::token;
 use syntax::print::{pp, pprust};
@@ -60,11 +62,11 @@ pub enum PpMode {
  */
 pub fn anon_src() -> @str { @"<anon>" }
 
-pub fn source_name(input: &input) -> @str {
+pub fn source_name(input: &Input) -> @str {
     match *input {
       // FIXME (#9639): This needs to handle non-utf8 paths
-      file_input(ref ifile) => ifile.as_str().unwrap().to_managed(),
-      str_input(_) => anon_src()
+      FileInput(ref ifile) => ifile.as_str().unwrap().to_managed(),
+      StrInput(_) => anon_src()
     }
 }
 
@@ -131,22 +133,22 @@ fn parse_cfgspecs(cfgspecs: ~[~str], demitter: @diagnostic::Emitter)
     }).collect::<ast::CrateConfig>()
 }
 
-pub enum input {
+pub enum Input {
     /// Load source from file
-    file_input(Path),
+    FileInput(Path),
     /// The string is the source
     // FIXME (#2319): Don't really want to box the source string
-    str_input(@str)
+    StrInput(@str)
 }
 
-pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
+pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &Input)
     -> ast::Crate {
     time(sess.time_passes(), "parsing", (), |_| {
         match *input {
-            file_input(ref file) => {
+            FileInput(ref file) => {
                 parse::parse_crate_from_file(&(*file), cfg.clone(), sess.parse_sess)
             }
-            str_input(src) => {
+            StrInput(src) => {
                 parse::parse_crate_from_source_str(
                     anon_src(), src, cfg.clone(), sess.parse_sess)
             }
@@ -163,6 +165,7 @@ pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
 /// standard library and prelude.
 pub fn phase_2_configure_and_expand(sess: Session,
                                     cfg: ast::CrateConfig,
+                                    loader: &mut CrateLoader,
                                     mut crate: ast::Crate)
                                     -> (ast::Crate, syntax::ast_map::Map) {
     let time_passes = sess.time_passes();
@@ -188,9 +191,14 @@ pub fn phase_2_configure_and_expand(sess: Session,
     crate = time(time_passes, "configuration 1", crate, |crate|
                  front::config::strip_unconfigured_items(crate));
 
-    crate = time(time_passes, "expansion", crate, |crate|
-                 syntax::ext::expand::expand_crate(sess.parse_sess, cfg.clone(),
-                                                   crate));
+    crate = time(time_passes, "expansion", crate, |crate| {
+        syntax::ext::expand::expand_crate(sess.parse_sess,
+                                          loader,
+                                          cfg.clone(),
+                                          crate)
+    });
+    // dump the syntax-time crates
+    sess.cstore.reset();
 
     // strip again, in case expansion added anything with a #[cfg].
     crate = time(time_passes, "configuration 2", crate, |crate|
@@ -248,6 +256,11 @@ pub fn phase_3_run_analysis_passes(sess: Session,
     time(time_passes, "looking for entry point", (),
          |_| middle::entry::find_entry_point(sess, crate, ast_map));
 
+    sess.macro_registrar_fn.with_mut(|r| *r =
+        time(time_passes, "looking for macro registrar", (), |_|
+            syntax::ext::registrar::find_macro_registrar(
+                sess.span_diagnostic, crate)));
+
     let freevars = time(time_passes, "freevar finding", (), |_|
                         freevars::annotate_freevars(def_map, crate));
 
@@ -431,7 +444,7 @@ pub fn stop_after_phase_5(sess: Session) -> bool {
     return false;
 }
 
-fn write_out_deps(sess: Session, input: &input, outputs: &OutputFilenames, crate: &ast::Crate)
+fn write_out_deps(sess: Session, input: &Input, outputs: &OutputFilenames, crate: &ast::Crate)
 {
     let lm = link::build_link_meta(sess, crate.attrs, &outputs.obj_filename,
                                        &mut ::util::sha2::Sha256::new());
@@ -447,12 +460,12 @@ fn write_out_deps(sess: Session, input: &input, outputs: &OutputFilenames, crate
         (true, Some(ref filename)) => filename.clone(),
         // Use default filename: crate source filename with extension replaced by ".d"
         (true, None) => match *input {
-            file_input(ref input_path) => {
+            FileInput(ref input_path) => {
                 let filestem = input_path.filestem().expect("input file must have stem");
                 let filename = out_filenames[0].dir_path().join(filestem).with_extension("d");
                 filename
             },
-            str_input(..) => {
+            StrInput(..) => {
                 sess.warn("can not write --dep-info without a filename when compiling stdin.");
                 return;
             },
@@ -482,7 +495,7 @@ fn write_out_deps(sess: Session, input: &input, outputs: &OutputFilenames, crate
     }
 }
 
-pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
+pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input,
                      outdir: &Option<Path>, output: &Option<Path>) {
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
@@ -491,7 +504,8 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
         let (expanded_crate, ast_map) = {
             let crate = phase_1_parse_input(sess, cfg.clone(), input);
             if stop_after_phase_1(sess) { return; }
-            phase_2_configure_and_expand(sess, cfg, crate)
+            let loader = &mut Loader::new(sess);
+            phase_2_configure_and_expand(sess, cfg, loader, crate)
         };
         let outputs = build_output_filenames(input, outdir, output,
                                              expanded_crate.attrs, sess);
@@ -573,13 +587,14 @@ fn post(&self, node: pprust::AnnNode) {
 
 pub fn pretty_print_input(sess: Session,
                           cfg: ast::CrateConfig,
-                          input: &input,
+                          input: &Input,
                           ppm: PpMode) {
     let crate = phase_1_parse_input(sess, cfg.clone(), input);
 
     let (crate, ast_map, is_expanded) = match ppm {
         PpmExpanded | PpmExpandedIdentified | PpmTyped => {
-            let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, crate);
+            let loader = &mut Loader::new(sess);
+            let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, loader, crate);
             (crate, Some(ast_map), true)
         }
         _ => (crate, None, false)
@@ -649,9 +664,9 @@ pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
 
     ("mips",   abi::Mips)];
 
-pub fn build_target_config(sopts: @session::options,
+pub fn build_target_config(sopts: @session::Options,
                            demitter: @diagnostic::Emitter)
-                           -> @session::config {
+                           -> @session::Config {
     let os = match get_os(sopts.target_triple) {
       Some(os) => os,
       None => early_error(demitter, "unknown operating system")
@@ -674,7 +689,7 @@ pub fn build_target_config(sopts: @session::options,
       abi::Arm => arm::get_target_strs(target_triple, os),
       abi::Mips => mips::get_target_strs(target_triple, os)
     };
-    let target_cfg = @session::config {
+    let target_cfg = @session::Config {
         os: os,
         arch: arch,
         target_strs: target_strs,
@@ -699,7 +714,7 @@ pub fn host_triple() -> ~str {
 pub fn build_session_options(binary: ~str,
                              matches: &getopts::Matches,
                              demitter: @diagnostic::Emitter)
-                             -> @session::options {
+                             -> @session::Options {
     let mut outputs = ~[];
     if matches.opt_present("rlib") {
         outputs.push(session::OutputRlib)
@@ -847,7 +862,7 @@ pub fn build_session_options(binary: ~str,
                        matches.opt_present("crate-name"),
                        matches.opt_present("crate-file-name"));
 
-    let sopts = @session::options {
+    let sopts = @session::Options {
         outputs: outputs,
         gc: gc,
         optimize: opt_level,
@@ -880,7 +895,7 @@ pub fn build_session_options(binary: ~str,
     return sopts;
 }
 
-pub fn build_session(sopts: @session::options, demitter: @diagnostic::Emitter)
+pub fn build_session(sopts: @session::Options, demitter: @diagnostic::Emitter)
                      -> Session {
     let codemap = @codemap::CodeMap::new();
     let diagnostic_handler =
@@ -890,7 +905,7 @@ pub fn build_session(sopts: @session::options, demitter: @diagnostic::Emitter)
     build_session_(sopts, codemap, demitter, span_diagnostic_handler)
 }
 
-pub fn build_session_(sopts: @session::options,
+pub fn build_session_(sopts: @session::Options,
                       cm: @codemap::CodeMap,
                       demitter: @diagnostic::Emitter,
                       span_diagnostic_handler: @diagnostic::SpanHandler)
@@ -899,7 +914,7 @@ pub fn build_session_(sopts: @session::options,
     let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler,
                                                     cm);
     let cstore = @CStore::new(token::get_ident_interner());
-    let filesearch = filesearch::mk_filesearch(
+    let filesearch = @filesearch::FileSearch::new(
         &sopts.maybe_sysroot,
         sopts.target_triple,
         sopts.addl_lib_search_paths);
@@ -912,6 +927,7 @@ pub fn build_session_(sopts: @session::options,
         // For a library crate, this is always none
         entry_fn: RefCell::new(None),
         entry_type: Cell::new(None),
+        macro_registrar_fn: RefCell::new(None),
         span_diagnostic: span_diagnostic_handler,
         filesearch: filesearch,
         building_library: Cell::new(false),
@@ -1011,7 +1027,7 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] {
                           for details)", "FEATURE"),
   optopt("", "android-cross-path",
          "The path to the Android NDK", "PATH"),
-  optflagopt("W", "warn",
+  optmulti("W", "warn",
                         "Set lint warnings", "OPT"),
   optmulti("A", "allow",
                         "Set lint allowed", "OPT"),
@@ -1030,7 +1046,7 @@ pub struct OutputFilenames {
     obj_filename: Path
 }
 
-pub fn build_output_filenames(input: &input,
+pub fn build_output_filenames(input: &Input,
                               odir: &Option<Path>,
                               ofile: &Option<Path>,
                               attrs: &[ast::Attribute],
@@ -1058,15 +1074,15 @@ pub fn build_output_filenames(input: &input,
           let dirpath = match *odir {
               Some(ref d) => (*d).clone(),
               None => match *input {
-                  str_input(_) => os::getcwd(),
-                  file_input(ref ifile) => (*ifile).dir_path()
+                  StrInput(_) => os::getcwd(),
+                  FileInput(ref ifile) => (*ifile).dir_path()
               }
           };
 
           let mut stem = match *input {
               // FIXME (#9639): This needs to handle non-utf8 paths
-              file_input(ref ifile) => (*ifile).filestem_str().unwrap().to_managed(),
-              str_input(_) => @"rust_out"
+              FileInput(ref ifile) => (*ifile).filestem_str().unwrap().to_managed(),
+              StrInput(_) => @"rust_out"
           };
 
           // If a crateid is present, we use it as the link name
index d701fed1a521fbde82ac271486efb07f2c907d0b..ebd6c06e2433cd92be2c15550caac28a1952dd1c 100644 (file)
@@ -31,7 +31,7 @@
 use std::cell::{Cell, RefCell};
 use std::hashmap::{HashMap,HashSet};
 
-pub struct config {
+pub struct Config {
     os: abi::Os,
     arch: abi::Architecture,
     target_strs: target_strs::t,
@@ -134,7 +134,7 @@ pub enum OptLevel {
 }
 
 #[deriving(Clone)]
-pub struct options {
+pub struct Options {
     // The crate config requested for the session, which may be combined
     // with additional crate configurations during the compile process
     outputs: ~[OutputStyle],
@@ -176,11 +176,6 @@ pub struct options {
     print_metas: (bool, bool, bool),
 }
 
-pub struct crate_metadata {
-    name: ~str,
-    data: ~[u8]
-}
-
 // The type of entry function, so
 // users can have their own entry
 // functions that don't start a
@@ -201,8 +196,8 @@ pub enum OutputStyle {
 }
 
 pub struct Session_ {
-    targ_cfg: @config,
-    opts: @options,
+    targ_cfg: @Config,
+    opts: @Options,
     cstore: @metadata::cstore::CStore,
     parse_sess: @ParseSess,
     codemap: @codemap::CodeMap,
@@ -210,6 +205,7 @@ pub struct Session_ {
     entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
     entry_type: Cell<Option<EntryFnType>>,
     span_diagnostic: @diagnostic::SpanHandler,
+    macro_registrar_fn: RefCell<Option<ast::DefId>>,
     filesearch: @filesearch::FileSearch,
     building_library: Cell<bool>,
     working_dir: Path,
@@ -374,8 +370,8 @@ pub fn intr(&self) -> @syntax::parse::token::IdentInterner {
 }
 
 /// Some reasonable defaults
-pub fn basic_options() -> @options {
-    @options {
+pub fn basic_options() -> @Options {
+    @Options {
         outputs: ~[],
         gc: false,
         optimize: No,
@@ -412,7 +408,7 @@ pub fn expect<T:Clone>(sess: Session, opt: Option<T>, msg: || -> ~str) -> T {
     diagnostic::expect(sess.diagnostic(), opt, msg)
 }
 
-pub fn building_library(options: &options, crate: &ast::Crate) -> bool {
+pub fn building_library(options: &Options, crate: &ast::Crate) -> bool {
     if options.test { return false }
     for output in options.outputs.iter() {
         match *output {
index c0732e93bee74a38192f8b53aa8c7c6b233f7261..d51f3e3f037c1414cf9b69b79f2555d1e3315103 100644 (file)
@@ -43,6 +43,8 @@
     ("non_ascii_idents", Active),
     ("thread_local", Active),
     ("link_args", Active),
+    ("phase", Active),
+    ("macro_registrar", Active),
 
     // These are used to test this portion of the compiler, they don't actually
     // mean anything
@@ -114,7 +116,15 @@ fn visit_view_item(&mut self, i: &ast::ViewItem, _: ()) {
                     }
                 }
             }
-            _ => {}
+            ast::ViewItemExternMod(..) => {
+                for attr in i.attrs.iter() {
+                    if "phase" == attr.name() {
+                        self.gate_feature("phase", attr.span,
+                                          "compile time crate loading is \
+                                           experimental and possibly buggy");
+                    }
+                }
+            }
         }
         visit::walk_view_item(self, i, ())
     }
@@ -151,6 +161,14 @@ fn visit_item(&mut self, i: &ast::Item, _:()) {
                 }
             }
 
+            ast::ItemFn(..) => {
+                if attr::contains_name(i.attrs, "macro_registrar") {
+                    self.gate_feature("macro_registrar", i.span,
+                                      "cross-crate macro exports are \
+                                       experimental and possibly buggy");
+                }
+            }
+
             _ => {}
         }
 
index c301318047c35471b596c37cbc5325102fe36881..f2bc03b21badb23e1a1c637c720a050284764d73 100644 (file)
@@ -21,6 +21,9 @@
 use syntax::opt_vec;
 use syntax::util::small_vector::SmallVector;
 
+// NOTE: upgrade to 0.10-pre after the next snapshot
+pub static VERSION: &'static str = "0.9";
+
 pub fn maybe_inject_libstd_ref(sess: Session, crate: ast::Crate)
                                -> ast::Crate {
     if use_std(&crate) {
@@ -53,11 +56,21 @@ struct StandardLibraryInjector {
     sess: Session,
 }
 
+pub fn with_version(crate: &str) -> Option<(@str, ast::StrStyle)> {
+    match option_env!("CFG_DISABLE_INJECT_STD_VERSION") {
+        Some("1") => None,
+        _ => {
+            Some((format!("{}\\#{}", crate, VERSION).to_managed(),
+                  ast::CookedStr))
+        }
+    }
+}
+
 impl fold::Folder for StandardLibraryInjector {
     fn fold_crate(&mut self, crate: ast::Crate) -> ast::Crate {
         let mut vis = ~[ast::ViewItem {
             node: ast::ViewItemExternMod(self.sess.ident_of("std"),
-                                         None,
+                                         with_version("std"),
                                          ast::DUMMY_NODE_ID),
             attrs: ~[],
             vis: ast::Private,
@@ -67,7 +80,7 @@ fn fold_crate(&mut self, crate: ast::Crate) -> ast::Crate {
         if use_uv(&crate) && !self.sess.building_library.get() {
             vis.push(ast::ViewItem {
                 node: ast::ViewItemExternMod(self.sess.ident_of("green"),
-                                             None,
+                                             with_version("green"),
                                              ast::DUMMY_NODE_ID),
                 attrs: ~[],
                 vis: ast::Private,
@@ -75,7 +88,7 @@ fn fold_crate(&mut self, crate: ast::Crate) -> ast::Crate {
             });
             vis.push(ast::ViewItem {
                 node: ast::ViewItemExternMod(self.sess.ident_of("rustuv"),
-                                             None,
+                                             with_version("rustuv"),
                                              ast::DUMMY_NODE_ID),
                 attrs: ~[],
                 vis: ast::Private,
index 26d6c5cf9e7890b0b2440c9bee07833afe0a0a1c..95bf171562d2fc5c112ed64d0ddb24efcaaf8331 100644 (file)
@@ -13,6 +13,8 @@
 
 use driver::session;
 use front::config;
+use front::std_inject::with_version;
+use metadata::creader::Loader;
 
 use std::cell::RefCell;
 use std::vec;
@@ -37,10 +39,10 @@ struct Test {
     should_fail: bool
 }
 
-struct TestCtxt {
+struct TestCtxt<'a> {
     sess: session::Session,
     path: RefCell<~[ast::Ident]>,
-    ext_cx: ExtCtxt,
+    ext_cx: ExtCtxt<'a>,
     testfns: RefCell<~[Test]>,
     is_extra: bool,
     config: ast::CrateConfig,
@@ -62,11 +64,11 @@ pub fn modify_for_testing(sess: session::Session,
     }
 }
 
-struct TestHarnessGenerator {
-    cx: TestCtxt,
+struct TestHarnessGenerator<'a> {
+    cx: TestCtxt<'a>,
 }
 
-impl fold::Folder for TestHarnessGenerator {
+impl<'a> fold::Folder for TestHarnessGenerator<'a> {
     fn fold_crate(&mut self, c: ast::Crate) -> ast::Crate {
         let folded = fold::noop_fold_crate(c, self);
 
@@ -154,9 +156,10 @@ fn nomain(cx: &TestCtxt, item: @ast::Item) -> @ast::Item {
 
 fn generate_test_harness(sess: session::Session, crate: ast::Crate)
                          -> ast::Crate {
+    let loader = &mut Loader::new(sess);
     let mut cx: TestCtxt = TestCtxt {
         sess: sess,
-        ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
+        ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(), loader),
         path: RefCell::new(~[]),
         testfns: RefCell::new(~[]),
         is_extra: is_extra(&crate),
@@ -292,7 +295,7 @@ fn mk_std(cx: &TestCtxt) -> ast::ViewItem {
                                           ast::DUMMY_NODE_ID))])
     } else {
         ast::ViewItemExternMod(id_extra,
-                               None,
+                               with_version("extra"),
                                ast::DUMMY_NODE_ID)
     };
     ast::ViewItem {
index eb4623d554bc10069e4442ccc9b5b099b348726a..8e847238cffafa0702b56f2503f6cfaeb4930d24 100644 (file)
@@ -227,14 +227,9 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
         return;
     }
 
-    // Display the available lint options if "-W help" or only "-W" is given.
     let lint_flags = vec::append(matches.opt_strs("W"),
                                  matches.opt_strs("warn"));
-
-    let show_lint_options = lint_flags.iter().any(|x| x == &~"help") ||
-        (matches.opt_present("W") && lint_flags.is_empty());
-
-    if show_lint_options {
+    if lint_flags.iter().any(|x| x == &~"help") {
         describe_warnings();
         return;
     }
@@ -260,9 +255,9 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
         let ifile = matches.free[0].as_slice();
         if "-" == ifile {
             let src = str::from_utf8_owned(io::stdin().read_to_end());
-            d::str_input(src.to_managed())
+            d::StrInput(src.to_managed())
         } else {
-            d::file_input(Path::new(ifile))
+            d::FileInput(Path::new(ifile))
         }
       }
       _ => d::early_error(demitter, "multiple input filenames provided")
@@ -286,12 +281,12 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
     let ls = matches.opt_present("ls");
     if ls {
         match input {
-          d::file_input(ref ifile) => {
+          d::FileInput(ref ifile) => {
             let mut stdout = io::stdout();
             d::list_metadata(sess, &(*ifile),
                                   &mut stdout as &mut io::Writer);
           }
-          d::str_input(_) => {
+          d::StrInput(_) => {
             d::early_error(demitter, "can not list metadata for stdin");
           }
         }
@@ -337,12 +332,12 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
 }
 
 fn parse_crate_attrs(sess: session::Session,
-                     input: &d::input) -> ~[ast::Attribute] {
+                     input: &d::Input) -> ~[ast::Attribute] {
     match *input {
-        d::file_input(ref ifile) => {
+        d::FileInput(ref ifile) => {
             parse::parse_crate_attrs_from_file(ifile, ~[], sess.parse_sess)
         }
-        d::str_input(src) => {
+        d::StrInput(src) => {
             parse::parse_crate_attrs_from_source_str(
                 d::anon_src(), src, ~[], sess.parse_sess)
         }
index 98f67b6442b5af53cbfbc004ea7c607f051fe4c7..c259fa6a61831317dab350cd64e3f004d63c9182 100644 (file)
@@ -1698,6 +1698,7 @@ pub fn LLVMDIBuilderCreateNameSpace(Builder: DIBuilderRef,
 
         pub fn LLVMDICompositeTypeSetTypeArray(CompositeType: ValueRef, TypeArray: ValueRef);
         pub fn LLVMTypeToString(Type: TypeRef) -> *c_char;
+        pub fn LLVMValueToString(value_ref: ValueRef) -> *c_char;
 
         pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
 
@@ -1847,8 +1848,10 @@ pub fn types_to_str(&self, tys: &[Type]) -> ~str {
 
     pub fn val_to_str(&self, val: ValueRef) -> ~str {
         unsafe {
-            let ty = Type::from_ref(llvm::LLVMTypeOf(val));
-            self.type_to_str(ty)
+            let s = llvm::LLVMValueToString(val);
+            let ret = from_c_str(s);
+            free(s as *c_void);
+            ret
         }
     }
 }
index 2d86a36dd60ab01219809355d47fe3c91968794c..09531e80ae59cf1d038f609195102ce8aa1c2800 100644 (file)
@@ -204,6 +204,10 @@ pub fn from_uint(value : uint) -> Option<astencode_tag> {
 pub static tag_native_libraries_name: uint = 0x105;
 pub static tag_native_libraries_kind: uint = 0x106;
 
+pub static tag_macro_registrar_fn: uint = 0x110;
+pub static tag_exported_macros: uint = 0x111;
+pub static tag_macro_def: uint = 0x112;
+
 #[deriving(Clone)]
 pub struct LinkMeta {
     crateid: CrateId,
index 6508da88f3d4e9b840c768c5d92790820021c69e..1d992833112063ac9be5b0dfc74e102a6f2965d6 100644 (file)
 
 //! Validates all used crates and extern libraries and loads their metadata
 
+use driver::{driver, session};
 use driver::session::Session;
+use metadata::csearch;
 use metadata::cstore;
 use metadata::decoder;
 use metadata::loader;
+use metadata::loader::Os;
 
 use std::cell::RefCell;
 use std::hashmap::HashMap;
@@ -23,6 +26,7 @@
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{Span, DUMMY_SP};
 use syntax::diagnostic::SpanHandler;
+use syntax::ext::base::{CrateLoader, MacroCrate};
 use syntax::parse::token;
 use syntax::parse::token::IdentInterner;
 use syntax::crateid::CrateId;
@@ -131,37 +135,65 @@ fn visit_crate(e: &Env, c: &ast::Crate) {
 }
 
 fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
+    let should_load = i.attrs.iter().all(|attr| {
+        "phase" != attr.name() ||
+            attr.meta_item_list().map_or(false, |phases| {
+                attr::contains_name(phases, "link")
+            })
+    });
+
+    if !should_load {
+        return;
+    }
+
+    match extract_crate_info(i) {
+        Some(info) => {
+            let cnum = resolve_crate(e, info.ident, info.name, info.version,
+                                     @"", i.span);
+            e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
+        }
+        None => ()
+    }
+}
+
+struct CrateInfo {
+    ident: @str,
+    name: @str,
+    version: @str,
+    id: ast::NodeId,
+}
+
+fn extract_crate_info(i: &ast::ViewItem) -> Option<CrateInfo> {
     match i.node {
-      ast::ViewItemExternMod(ident, path_opt, id) => {
-          let ident = token::ident_to_str(&ident);
-          debug!("resolving extern mod stmt. ident: {:?} path_opt: {:?}",
-                 ident, path_opt);
-          let (name, version) = match path_opt {
-              Some((path_str, _)) => {
-                  let crateid: Option<CrateId> = from_str(path_str);
-                  match crateid {
-                      None => (@"", @""),
-                      Some(crateid) => {
-                          let version = match crateid.version {
-                              None => @"",
-                              Some(ref ver) => ver.to_managed(),
-                          };
-                          (crateid.name.to_managed(), version)
-                      }
-                  }
-              }
-              None => (ident, @""),
-          };
-          let cnum = resolve_crate(e,
-                                   ident,
-                                   name,
-                                   version,
-                                   @"",
-                                   i.span);
-          e.sess.cstore.add_extern_mod_stmt_cnum(id, cnum);
-      }
-      _ => ()
-  }
+        ast::ViewItemExternMod(ident, path_opt, id) => {
+            let ident = token::ident_to_str(&ident);
+            debug!("resolving extern mod stmt. ident: {:?} path_opt: {:?}",
+                   ident, path_opt);
+            let (name, version) = match path_opt {
+                Some((path_str, _)) => {
+                    let crateid: Option<CrateId> = from_str(path_str);
+                    match crateid {
+                        None => (@"", @""),
+                        Some(crateid) => {
+                            let version = match crateid.version {
+                                None => @"",
+                                Some(ref ver) => ver.to_managed(),
+                            };
+                            (crateid.name.to_managed(), version)
+                        }
+                    }
+                }
+                None => (ident, @""),
+            };
+            Some(CrateInfo {
+                  ident: ident,
+                  name: name,
+                  version: version,
+                  id: id,
+            })
+        }
+        _ => None
+    }
 }
 
 fn visit_item(e: &Env, i: &ast::Item) {
@@ -355,3 +387,46 @@ fn resolve_crate_deps(e: &mut Env, cdata: &[u8]) -> cstore::cnum_map {
     }
     return @RefCell::new(cnum_map);
 }
+
+pub struct Loader {
+    priv env: Env,
+}
+
+impl Loader {
+    pub fn new(sess: Session) -> Loader {
+        let os = driver::get_os(driver::host_triple()).unwrap();
+        let os = session::sess_os_to_meta_os(os);
+        Loader {
+            env: Env {
+                sess: sess,
+                os: os,
+                crate_cache: @RefCell::new(~[]),
+                next_crate_num: 1,
+                intr: token::get_ident_interner(),
+            }
+        }
+    }
+}
+
+impl CrateLoader for Loader {
+    fn load_crate(&mut self, crate: &ast::ViewItem) -> MacroCrate {
+        let info = extract_crate_info(crate).unwrap();
+        let cnum = resolve_crate(&mut self.env, info.ident, info.name,
+                                 info.version, @"", crate.span);
+        let library = self.env.sess.cstore.get_used_crate_source(cnum).unwrap();
+        MacroCrate {
+            lib: library.dylib,
+            cnum: cnum
+        }
+    }
+
+    fn get_exported_macros(&mut self, cnum: ast::CrateNum) -> ~[@ast::Item] {
+        csearch::get_exported_macros(self.env.sess.cstore, cnum)
+    }
+
+    fn get_registrar_symbol(&mut self, cnum: ast::CrateNum) -> Option<~str> {
+        let cstore = self.env.sess.cstore;
+        csearch::get_macro_registrar_fn(cstore, cnum)
+            .map(|did| csearch::get_symbol(cstore, did))
+    }
+}
index 6dad364e661ba9a361f02debcd7460b054703421..9955186da462faaef9b1e75c409f504183539830 100644 (file)
@@ -301,3 +301,16 @@ pub fn get_trait_of_method(cstore: @cstore::CStore,
     decoder::get_trait_of_method(cdata, def_id.node, tcx)
 }
 
+pub fn get_macro_registrar_fn(cstore: @cstore::CStore,
+                              crate_num: ast::CrateNum)
+                              -> Option<ast::DefId> {
+    let cdata = cstore.get_crate_data(crate_num);
+    decoder::get_macro_registrar_fn(cdata)
+}
+
+pub fn get_exported_macros(cstore: @cstore::CStore,
+                           crate_num: ast::CrateNum)
+                           -> ~[@ast::Item] {
+    let cdata = cstore.get_crate_data(crate_num);
+    decoder::get_exported_macros(cdata)
+}
index 5be69e9452c0355c5dfa42987248fa1576d9e8df..024e214a2fe716d453e34ab4b99170669c349e32 100644 (file)
@@ -53,7 +53,7 @@ pub enum NativeLibaryKind {
 
 // Where a crate came from on the local filesystem. One of these two options
 // must be non-None.
-#[deriving(Eq)]
+#[deriving(Eq, Clone)]
 pub struct CrateSource {
     dylib: Option<Path>,
     rlib: Option<Path>,
@@ -123,6 +123,21 @@ pub fn add_used_crate_source(&self, src: CrateSource) {
         }
     }
 
+    pub fn get_used_crate_source(&self, cnum: ast::CrateNum)
+                                     -> Option<CrateSource> {
+        let mut used_crate_sources = self.used_crate_sources.borrow_mut();
+        used_crate_sources.get().iter().find(|source| source.cnum == cnum)
+            .map(|source| source.clone())
+    }
+
+    pub fn reset(&self) {
+        self.metas.with_mut(|s| s.clear());
+        self.extern_mod_crate_map.with_mut(|s| s.clear());
+        self.used_crate_sources.with_mut(|s| s.clear());
+        self.used_libraries.with_mut(|s| s.clear());
+        self.used_link_args.with_mut(|s| s.clear());
+    }
+
     pub fn get_used_crates(&self, prefer: LinkagePreference)
                            -> ~[(ast::CrateNum, Option<Path>)] {
         let used_crate_sources = self.used_crate_sources.borrow();
index ca35b1ae96b0285a3d5a717797de067fbce0e7f2..abf5b051c7de7342d7cffabb554f1550d29e415f 100644 (file)
@@ -23,6 +23,7 @@
 use middle::ty::{ImplContainer, TraitContainer};
 use middle::ty;
 use middle::typeck;
+use middle::astencode;
 use middle::astencode::vtable_decoder_helpers;
 
 use std::at_vec;
@@ -782,7 +783,7 @@ fn get_mutability(ch: u8) -> ast::Mutability {
     match explicit_self_kind as char {
         's' => ast::SelfStatic,
         'v' => ast::SelfValue(get_mutability(string[1])),
-        '@' => ast::SelfBox(get_mutability(string[1])),
+        '@' => ast::SelfBox,
         '~' => ast::SelfUniq(get_mutability(string[1])),
         // FIXME(#4846) expl. region
         '&' => ast::SelfRegion(None, get_mutability(string[1])),
@@ -1275,3 +1276,19 @@ pub fn get_native_libraries(cdata: Cmd) -> ~[(cstore::NativeLibaryKind, ~str)] {
     });
     return result;
 }
+
+pub fn get_macro_registrar_fn(cdata: Cmd) -> Option<ast::DefId> {
+    reader::maybe_get_doc(reader::Doc(cdata.data()), tag_macro_registrar_fn)
+        .map(|doc| item_def_id(doc, cdata))
+}
+
+pub fn get_exported_macros(cdata: Cmd) -> ~[@ast::Item] {
+    let macros = reader::get_doc(reader::Doc(cdata.data()),
+                                 tag_exported_macros);
+    let mut result = ~[];
+    reader::tagged_docs(macros, tag_macro_def, |macro_doc| {
+        result.push(astencode::decode_exported_macro(macro_doc));
+        true
+    });
+    result
+}
index c46b573c1e0e64f63101d1a34a3a315aef5b5387..b015638435b89a699458f020be873d4867aa0cb8 100644 (file)
@@ -79,6 +79,8 @@ struct Stats {
     dep_bytes: Cell<u64>,
     lang_item_bytes: Cell<u64>,
     native_lib_bytes: Cell<u64>,
+    macro_registrar_fn_bytes: Cell<u64>,
+    macro_defs_bytes: Cell<u64>,
     impl_bytes: Cell<u64>,
     misc_bytes: Cell<u64>,
     item_bytes: Cell<u64>,
@@ -687,9 +689,8 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::Explic
             ebml_w.writer.write(&[ '&' as u8 ]);
             encode_mutability(ebml_w, m);
         }
-        SelfBox(m) => {
+        SelfBox => {
             ebml_w.writer.write(&[ '@' as u8 ]);
-            encode_mutability(ebml_w, m);
         }
         SelfUniq(m) => {
             ebml_w.writer.write(&[ '~' as u8 ]);
@@ -1288,7 +1289,9 @@ fn add_to_index(item: &Item, ebml_w: &writer::Encoder,
         // Encode inherent implementations for this trait.
         encode_inherent_implementations(ecx, ebml_w, def_id);
       }
-      ItemMac(..) => fail!("item macros unimplemented")
+      ItemMac(..) => {
+        // macros are encoded separately
+      }
     }
 }
 
@@ -1692,6 +1695,50 @@ fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
     ebml_w.end_tag();
 }
 
+fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
+    let ptr = ecx.tcx.sess.macro_registrar_fn.borrow();
+    match *ptr.get() {
+        Some(did) => {
+            ebml_w.start_tag(tag_macro_registrar_fn);
+            encode_def_id(ebml_w, did);
+            ebml_w.end_tag();
+        }
+        None => {}
+    }
+}
+
+struct MacroDefVisitor<'a, 'b> {
+    ecx: &'a EncodeContext<'a>,
+    ebml_w: &'a mut writer::Encoder<'b>
+}
+
+impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> {
+    fn visit_item(&mut self, item: &Item, _: ()) {
+        match item.node {
+            ItemMac(..) => {
+                self.ebml_w.start_tag(tag_macro_def);
+                astencode::encode_exported_macro(self.ebml_w, item);
+                self.ebml_w.end_tag();
+            }
+            _ => {}
+        }
+    }
+}
+
+fn encode_macro_defs(ecx: &EncodeContext,
+                     crate: &Crate,
+                     ebml_w: &mut writer::Encoder) {
+    ebml_w.start_tag(tag_exported_macros);
+    {
+        let mut visitor = MacroDefVisitor {
+            ecx: ecx,
+            ebml_w: ebml_w,
+        };
+        visit::walk_crate(&mut visitor, crate, ());
+    }
+    ebml_w.end_tag();
+}
+
 struct ImplVisitor<'a,'b> {
     ecx: &'a EncodeContext<'a>,
     ebml_w: &'a mut writer::Encoder<'b>,
@@ -1816,6 +1863,8 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate)
         dep_bytes: Cell::new(0),
         lang_item_bytes: Cell::new(0),
         native_lib_bytes: Cell::new(0),
+        macro_registrar_fn_bytes: Cell::new(0),
+        macro_defs_bytes: Cell::new(0),
         impl_bytes: Cell::new(0),
         misc_bytes: Cell::new(0),
         item_bytes: Cell::new(0),
@@ -1874,6 +1923,16 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate)
     encode_native_libraries(&ecx, &mut ebml_w);
     ecx.stats.native_lib_bytes.set(ebml_w.writer.tell() - i);
 
+    // Encode the macro registrar function
+    i = ebml_w.writer.tell();
+    encode_macro_registrar_fn(&ecx, &mut ebml_w);
+    ecx.stats.macro_registrar_fn_bytes.set(ebml_w.writer.tell() - i);
+
+    // Encode macro definitions
+    i = ebml_w.writer.tell();
+    encode_macro_defs(&ecx, crate, &mut ebml_w);
+    ecx.stats.macro_defs_bytes.set(ebml_w.writer.tell() - i);
+
     // Encode the def IDs of impls, for coherence checking.
     i = ebml_w.writer.tell();
     encode_impls(&ecx, crate, &mut ebml_w);
@@ -1906,17 +1965,19 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate)
         }
 
         println!("metadata stats:");
-        println!("    inline bytes: {}", ecx.stats.inline_bytes.get());
-        println!(" attribute bytes: {}", ecx.stats.attr_bytes.get());
-        println!("       dep bytes: {}", ecx.stats.dep_bytes.get());
-        println!(" lang item bytes: {}", ecx.stats.lang_item_bytes.get());
-        println!("    native bytes: {}", ecx.stats.native_lib_bytes.get());
-        println!("      impl bytes: {}", ecx.stats.impl_bytes.get());
-        println!("      misc bytes: {}", ecx.stats.misc_bytes.get());
-        println!("      item bytes: {}", ecx.stats.item_bytes.get());
-        println!("     index bytes: {}", ecx.stats.index_bytes.get());
-        println!("      zero bytes: {}", ecx.stats.zero_bytes.get());
-        println!("     total bytes: {}", ecx.stats.total_bytes.get());
+        println!("         inline bytes: {}", ecx.stats.inline_bytes.get());
+        println!("      attribute bytes: {}", ecx.stats.attr_bytes.get());
+        println!("            dep bytes: {}", ecx.stats.dep_bytes.get());
+        println!("      lang item bytes: {}", ecx.stats.lang_item_bytes.get());
+        println!("         native bytes: {}", ecx.stats.native_lib_bytes.get());
+        println!("macro registrar bytes: {}", ecx.stats.macro_registrar_fn_bytes.get());
+        println!("      macro def bytes: {}", ecx.stats.macro_defs_bytes.get());
+        println!("           impl bytes: {}", ecx.stats.impl_bytes.get());
+        println!("           misc bytes: {}", ecx.stats.misc_bytes.get());
+        println!("           item bytes: {}", ecx.stats.item_bytes.get());
+        println!("          index bytes: {}", ecx.stats.index_bytes.get());
+        println!("           zero bytes: {}", ecx.stats.zero_bytes.get());
+        println!("          total bytes: {}", ecx.stats.total_bytes.get());
     }
 }
 
index f804338f4ff5bab10a6fb8da569062f2732837d4..f8e7a28d27708117066d7c43f7c2c26dd99ff7a2 100644 (file)
@@ -25,132 +25,117 @@ pub enum FileMatch { FileMatches, FileDoesntMatch }
 /// a file found in that directory.
 pub type pick<'a> = 'a |path: &Path| -> FileMatch;
 
-pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
-    if path.filename() == Some(file.as_vec()) {
-        Some(path.clone())
-    } else {
-        None
-    }
-}
-
-pub trait FileSearch {
-    fn sysroot(&self) -> @Path;
-    fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch);
-    fn get_target_lib_path(&self) -> Path;
-    fn get_target_lib_file_path(&self, file: &Path) -> Path;
+pub struct FileSearch {
+    sysroot: @Path,
+    addl_lib_search_paths: @RefCell<HashSet<Path>>,
+    target_triple: ~str
 }
 
-pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
-                     target_triple: &str,
-                     addl_lib_search_paths: @RefCell<HashSet<Path>>)
-                  -> @FileSearch {
-    struct FileSearchImpl {
-        sysroot: @Path,
-        addl_lib_search_paths: @RefCell<HashSet<Path>>,
-        target_triple: ~str
-    }
-    impl FileSearch for FileSearchImpl {
-        fn sysroot(&self) -> @Path { self.sysroot }
-
-        fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch) {
-            let mut visited_dirs = HashSet::new();
-            let mut found = false;
-
-            let addl_lib_search_paths = self.addl_lib_search_paths.borrow();
-            debug!("filesearch: searching additional lib search paths [{:?}]",
-                   addl_lib_search_paths.get().len());
-            for path in addl_lib_search_paths.get().iter() {
-                match f(path) {
-                    FileMatches => found = true,
-                    FileDoesntMatch => ()
-                }
-                visited_dirs.insert(path.as_vec().to_owned());
+impl FileSearch {
+    pub fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch) {
+        let mut visited_dirs = HashSet::new();
+        let mut found = false;
+
+        let addl_lib_search_paths = self.addl_lib_search_paths.borrow();
+        debug!("filesearch: searching additional lib search paths [{:?}]",
+               addl_lib_search_paths.get().len());
+        for path in addl_lib_search_paths.get().iter() {
+            match f(path) {
+                FileMatches => found = true,
+                FileDoesntMatch => ()
             }
+            visited_dirs.insert(path.as_vec().to_owned());
+        }
 
-            debug!("filesearch: searching target lib path");
-            let tlib_path = make_target_lib_path(self.sysroot,
-                                        self.target_triple);
-            if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
-                match f(&tlib_path) {
-                    FileMatches => found = true,
-                    FileDoesntMatch => ()
-                }
+        debug!("filesearch: searching target lib path");
+        let tlib_path = make_target_lib_path(self.sysroot,
+                                    self.target_triple);
+        if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
+            match f(&tlib_path) {
+                FileMatches => found = true,
+                FileDoesntMatch => ()
             }
-            visited_dirs.insert(tlib_path.as_vec().to_owned());
-            // Try RUST_PATH
-            if !found {
-                let rustpath = rust_path();
-                for path in rustpath.iter() {
-                    let tlib_path = make_rustpkg_target_lib_path(path, self.target_triple);
-                    debug!("is {} in visited_dirs? {:?}", tlib_path.display(),
-                            visited_dirs.contains_equiv(&tlib_path.as_vec().to_owned()));
-
-                    if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
-                        visited_dirs.insert(tlib_path.as_vec().to_owned());
-                        // Don't keep searching the RUST_PATH if one match turns up --
-                        // if we did, we'd get a "multiple matching crates" error
-                        match f(&tlib_path) {
-                           FileMatches => {
-                               break;
-                           }
-                           FileDoesntMatch => ()
-                        }
+        }
+        visited_dirs.insert(tlib_path.as_vec().to_owned());
+        // Try RUST_PATH
+        if !found {
+            let rustpath = rust_path();
+            for path in rustpath.iter() {
+                let tlib_path = make_rustpkg_target_lib_path(path, self.target_triple);
+                debug!("is {} in visited_dirs? {:?}", tlib_path.display(),
+                        visited_dirs.contains_equiv(&tlib_path.as_vec().to_owned()));
+
+                if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
+                    visited_dirs.insert(tlib_path.as_vec().to_owned());
+                    // Don't keep searching the RUST_PATH if one match turns up --
+                    // if we did, we'd get a "multiple matching crates" error
+                    match f(&tlib_path) {
+                       FileMatches => {
+                           break;
+                       }
+                       FileDoesntMatch => ()
                     }
                 }
             }
         }
-        fn get_target_lib_path(&self) -> Path {
-            make_target_lib_path(self.sysroot, self.target_triple)
-        }
-        fn get_target_lib_file_path(&self, file: &Path) -> Path {
-            let mut p = self.get_target_lib_path();
-            p.push(file);
-            p
-        }
     }
 
-    let sysroot = get_sysroot(maybe_sysroot);
-    debug!("using sysroot = {}", sysroot.display());
-    @FileSearchImpl {
-        sysroot: sysroot,
-        addl_lib_search_paths: addl_lib_search_paths,
-        target_triple: target_triple.to_owned()
-    } as @FileSearch
-}
+    pub fn get_target_lib_path(&self) -> Path {
+        make_target_lib_path(self.sysroot, self.target_triple)
+    }
 
-pub fn search(filesearch: @FileSearch, pick: pick) {
-    filesearch.for_each_lib_search_path(|lib_search_path| {
-        debug!("searching {}", lib_search_path.display());
-        match io::result(|| fs::readdir(lib_search_path)) {
-            Ok(files) => {
-                let mut rslt = FileDoesntMatch;
-                let is_rlib = |p: & &Path| {
-                    p.extension_str() == Some("rlib")
-                };
-                // Reading metadata out of rlibs is faster, and if we find both
-                // an rlib and a dylib we only read one of the files of
-                // metadata, so in the name of speed, bring all rlib files to
-                // the front of the search list.
-                let files1 = files.iter().filter(|p| is_rlib(p));
-                let files2 = files.iter().filter(|p| !is_rlib(p));
-                for path in files1.chain(files2) {
-                    debug!("testing {}", path.display());
-                    let maybe_picked = pick(path);
-                    match maybe_picked {
-                        FileMatches => {
-                            debug!("picked {}", path.display());
-                            rslt = FileMatches;
-                        }
-                        FileDoesntMatch => {
-                            debug!("rejected {}", path.display());
+    pub fn get_target_lib_file_path(&self, file: &Path) -> Path {
+        let mut p = self.get_target_lib_path();
+        p.push(file);
+        p
+    }
+
+    pub fn search(&self, pick: pick) {
+        self.for_each_lib_search_path(|lib_search_path| {
+            debug!("searching {}", lib_search_path.display());
+            match io::result(|| fs::readdir(lib_search_path)) {
+                Ok(files) => {
+                    let mut rslt = FileDoesntMatch;
+                    let is_rlib = |p: & &Path| {
+                        p.extension_str() == Some("rlib")
+                    };
+                    // Reading metadata out of rlibs is faster, and if we find both
+                    // an rlib and a dylib we only read one of the files of
+                    // metadata, so in the name of speed, bring all rlib files to
+                    // the front of the search list.
+                    let files1 = files.iter().filter(|p| is_rlib(p));
+                    let files2 = files.iter().filter(|p| !is_rlib(p));
+                    for path in files1.chain(files2) {
+                        debug!("testing {}", path.display());
+                        let maybe_picked = pick(path);
+                        match maybe_picked {
+                            FileMatches => {
+                                debug!("picked {}", path.display());
+                                rslt = FileMatches;
+                            }
+                            FileDoesntMatch => {
+                                debug!("rejected {}", path.display());
+                            }
                         }
                     }
+                    rslt
                 }
-                rslt
+                Err(..) => FileDoesntMatch,
             }
-            Err(..) => FileDoesntMatch,
+        });
+    }
+
+    pub fn new(maybe_sysroot: &Option<@Path>,
+               target_triple: &str,
+               addl_lib_search_paths: @RefCell<HashSet<Path>>) -> FileSearch {
+        let sysroot = get_sysroot(maybe_sysroot);
+        debug!("using sysroot = {}", sysroot.display());
+        FileSearch{
+            sysroot: sysroot,
+            addl_lib_search_paths: addl_lib_search_paths,
+            target_triple: target_triple.to_owned()
         }
-    });
+    }
 }
 
 pub fn relative_target_lib_path(target_triple: &str) -> Path {
@@ -244,7 +229,7 @@ pub fn rust_path() -> ~[Path] {
 // The name of the directory rustc expects libraries to be located.
 // On Unix should be "lib", on windows "bin"
 pub fn libdir() -> ~str {
-    (env!("LIBDIR_RELATIVE")).to_owned()
+    (env!("CFG_LIBDIR_RELATIVE")).to_owned()
 }
 
 // The name of rustc's own place to organize libraries.
index 12bfcb4b1983c5c3fb52a6ce2d85a48e07c3f544..72f2e1baddd7bdd7adb4a2d742382c8b49404358 100644 (file)
@@ -17,7 +17,6 @@
 use metadata::decoder;
 use metadata::encoder;
 use metadata::filesearch::{FileMatches, FileDoesntMatch};
-use metadata::filesearch;
 use syntax::codemap::Span;
 use syntax::diagnostic::SpanHandler;
 use syntax::parse::token::IdentInterner;
@@ -89,7 +88,7 @@ fn find_library_crate(&self) -> Option<Library> {
         let rlib_prefix = format!("lib{}-", crate_name);
 
         let mut matches = ~[];
-        filesearch::search(filesearch, |path| {
+        filesearch.search(|path| {
             match path.filename_str() {
                 None => FileDoesntMatch,
                 Some(file) => {
index 261cb15a7aac5d51e61c467c71b6cd1342cbbc58..1f33ef2f41be6790ee63b3ea9f3783e68512a3a4 100644 (file)
@@ -343,7 +343,7 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
         return ty::mk_self(st.tcx, did);
       }
       '@' => return ty::mk_box(st.tcx, parse_ty(st, |x,y| conv(x,y))),
-      '~' => return ty::mk_uniq(st.tcx, parse_mt(st, |x,y| conv(x,y))),
+      '~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))),
       '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))),
       '&' => {
         let r = parse_region(st, |x,y| conv(x,y));
index aca3d9000ded0e7b02fe75e0d310665c2da593e8..657522b836b3adc1e14821c99ec261a17e513238 100644 (file)
@@ -292,7 +292,7 @@ fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
             mywrite!(w, "]");
         }
         ty::ty_box(typ) => { mywrite!(w, "@"); enc_ty(w, cx, typ); }
-        ty::ty_uniq(mt) => { mywrite!(w, "~"); enc_mt(w, cx, mt); }
+        ty::ty_uniq(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); }
         ty::ty_ptr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
         ty::ty_rptr(r, mt) => {
             mywrite!(w, "&");
index 1b3d91e024ff26bec6eb2ccfe9093951d581ed75..5cc522a6e44974ae23a177de410487cada7475ac 100644 (file)
 use c = metadata::common;
 use cstore = metadata::cstore;
 use driver::session::Session;
-use e = metadata::encoder;
 use metadata::decoder;
+use e = metadata::encoder;
+use middle::freevars::freevar_entry;
+use middle::region;
 use metadata::tydecode;
 use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
                          RegionParameter};
 use metadata::tyencode;
-use middle::freevars::freevar_entry;
 use middle::typeck::{method_origin, method_map_entry};
 use middle::{ty, typeck, moves};
 use middle;
@@ -107,6 +108,13 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
            ebml_w.writer.tell());
 }
 
+pub fn encode_exported_macro(ebml_w: &mut writer::Encoder, i: &ast::Item) {
+    match i.node {
+        ast::ItemMac(..) => encode_ast(ebml_w, ast::IIItem(@i.clone())),
+        _ => fail!("expected a macro")
+    }
+}
+
 pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
                            tcx: ty::ctxt,
                            maps: Maps,
@@ -146,6 +154,7 @@ pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
         debug!("< Decoded inlined fn: {}::{}",
                ast_map::path_to_str(path, token::get_ident_interner()),
                tcx.sess.str_of(ident));
+        region::resolve_inlined_item(tcx.sess, &tcx.region_maps, &ii);
         decode_side_tables(xcx, ast_doc);
         match ii {
           ast::IIItem(i) => {
@@ -159,6 +168,13 @@ pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
     }
 }
 
+pub fn decode_exported_macro(par_doc: ebml::Doc) -> @ast::Item {
+    match decode_ast(par_doc) {
+        ast::IIItem(item) => item,
+        _ => fail!("expected item")
+    }
+}
+
 // ______________________________________________________________________
 // Enumerating the IDs which appear in an AST
 
index 3ffb678d1be8dadac144f55eeb0f7bbdaba6d067..286365f8c13fa45bfd4c9feb0fabffdbf90abcd1 100644 (file)
@@ -248,7 +248,7 @@ struct defined in `middle::borrowck`. Formally, we define `LOAN` as
 2. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed
 the lifetime of the value being borrowed. This pass is also
 responsible for inserting root annotations to keep managed values
-alive and for dynamically freezing `@mut` boxes.
+alive.
 
 3. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the
 restrictions to maintain memory safety. These are the restrictions
@@ -308,22 +308,17 @@ struct defined in `middle::borrowck`. Formally, we define `LOAN` as
 
 ### Checking mutability of mutable pointer types
 
-`&mut T` and `@mut T` can be frozen, so it is acceptable to borrow
-them as either imm or mut:
+`&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut:
 
     MUTABILITY(*LV, MQ)                 // M-Deref-Borrowed-Mut
       TYPE(LV) = &mut Ty
 
-    MUTABILITY(*LV, MQ)                 // M-Deref-Managed-Mut
-      TYPE(LV) = @mut Ty
-
 ## Checking lifetime
 
-These rules aim to ensure that no data is borrowed for a scope that
-exceeds its lifetime. In addition, these rules manage the rooting and
-dynamic freezing of `@` and `@mut` values. These two computations wind
-up being intimately related. Formally, we define a predicate
-`LIFETIME(LV, LT, MQ)`, which states that "the lvalue `LV` can be
+These rules aim to ensure that no data is borrowed for a scope that exceeds
+its lifetime. In addition, these rules manage the rooting of `@` values.
+These two computations wind up being intimately related. Formally, we define
+a predicate `LIFETIME(LV, LT, MQ)`, which states that "the lvalue `LV` can be
 safely borrowed for the lifetime `LT` with mutability `MQ`". The Rust
 code corresponding to this predicate is the module
 `middle::borrowck::gather_loans::lifetime`.
@@ -352,7 +347,7 @@ struct defined in `middle::borrowck`. Formally, we define `LOAN` as
 is a conservative approximation, since there may be other aliases fo
 that same managed box that would cause it to live longer:
 
-      SCOPE(*LV) = SCOPE(LV) if LV has type @T or @mut T
+      SCOPE(*LV) = SCOPE(LV) if LV has type @T
 
 The scope of a borrowed referent is the scope associated with the
 pointer.  This is a conservative approximation, since the data that
@@ -441,29 +436,6 @@ struct defined in `middle::borrowck`. Formally, we define `LOAN` as
 stack when `*LV` is evaluated, and that this root can be released when
 the scope `LT` exits.
 
-### Checking lifetime for derefs of managed, mutable pointers
-
-Loans of the contents of mutable managed pointers are simpler in some
-ways that loans of immutable managed pointers, because we can never
-rely on the user to root them (since the contents are, after all,
-mutable). This means that the burden always falls to the compiler, so
-there is only one rule:
-
-    LIFETIME(*LV, LT, MQ)              // L-Deref-Managed-Mut-Compiler-Root
-      TYPE(LV) = @mut Ty
-      LT <= innermost enclosing loop/func
-      ROOT LV at *LV for LT
-      LOCK LV at *LV as MQ for LT
-
-Note that there is an additional clause this time `LOCK LV at *LV as
-MQ for LT`.  This clause states that in addition to rooting `LV`, the
-compiler should also "lock" the box dynamically, meaning that we
-register that the box has been borrowed as mutable or immutable,
-depending on `MQ`. This lock will fail if the box has already been
-borrowed and either the old loan or the new loan is a mutable loan
-(multiple immutable loans are okay). The lock is released as we exit
-the scope `LT`.
-
 ## Computing the restrictions
 
 The final rules govern the computation of *restrictions*, meaning that
@@ -835,15 +807,6 @@ fn foo(t0: & &mut int) {
 prevent `const` borrows of the base pointer when the referent is
 borrowed.
 
-### Restrictions for loans of mutable managed referents
-
-With `@mut` referents, we don't make any static guarantees.  But as a
-convenience, we still register a restriction against `*LV`, because
-that way if we *can* find a simple static error, we will:
-
-    RESTRICTIONS(*LV, LT, ACTIONS) = [*LV, ACTIONS]   // R-Deref-Managed-Borrowed
-      TYPE(LV) = @mut Ty
-
 # Moves and initialization
 
 The borrow checker is also in charge of ensuring that:
index a7f75b9dcc1099e318866095bd48133fae1a19dd..9a4869fb6d1d02ce80b957254594e9aed1435d72 100644 (file)
@@ -67,6 +67,9 @@ fn tcx(&self) -> ty::ctxt {
 
     fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) -> R {
         //! Main routine. Walks down `cmt` until we find the "guarantor".
+        debug!("guarantee_lifetime.check(cmt={}, loan_region={})",
+               cmt.repr(self.bccx.tcx),
+               self.loan_region.repr(self.bccx.tcx));
 
         match cmt.cat {
             mc::cat_rvalue(..) |
@@ -137,7 +140,7 @@ fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) -> R {
                 //
                 // As a second example, consider *this* scenario:
                 //
-                //    let x = @mut @Some(3);
+                //    let x = @@Some(3);
                 //    match x { @@Some(y) {...} @@None {...} }
                 //
                 // Here again, `x` need only be rooted in the `some` arm.
@@ -156,7 +159,7 @@ fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) -> R {
                 // with a second basic block.  However, the naive approach
                 // also yielded suboptimal results for patterns like:
                 //
-                //    let x = @mut @...;
+                //    let x = @@...;
                 //    match x { @@some_variant(y) | @@some_other_variant(y) =>
                 //
                 // The reason is that we would root the value once for
@@ -220,7 +223,7 @@ fn check_root(&self,
 
         // If inside of a match arm, expand the rooting to the entire
         // match. See the detailed discussion in `check()` above.
-        let mut root_scope = match discr_scope {
+        let root_scope = match discr_scope {
             None => root_scope,
             Some(id) => {
                 if self.bccx.is_subscope_of(root_scope, id) {
@@ -231,17 +234,6 @@ fn check_root(&self,
             }
         };
 
-        // FIXME(#3511) grow to the nearest cleanup scope---this can
-        // cause observable errors if freezing!
-        if !self.bccx.tcx.region_maps.is_cleanup_scope(root_scope) {
-            debug!("{:?} is not a cleanup scope, adjusting", root_scope);
-
-            let cleanup_scope =
-                self.bccx.tcx.region_maps.cleanup_scope(root_scope);
-
-            root_scope = cleanup_scope;
-        }
-
         // Add a record of what is required
         let rm_key = root_map_key {id: cmt_deref.id, derefs: derefs};
         let root_info = RootInfo {scope: root_scope};
@@ -301,8 +293,8 @@ fn scope(&self, cmt: mc::cmt) -> ty::Region {
         // See the SCOPE(LV) function in doc.rs
 
         match cmt.cat {
-            mc::cat_rvalue(cleanup_scope_id) => {
-                ty::ReScope(cleanup_scope_id)
+            mc::cat_rvalue(temp_scope) => {
+                temp_scope
             }
             mc::cat_copied_upvar(_) => {
                 ty::ReScope(self.item_scope_id)
@@ -313,7 +305,7 @@ fn scope(&self, cmt: mc::cmt) -> ty::Region {
             mc::cat_local(local_id) |
             mc::cat_arg(local_id) |
             mc::cat_self(local_id) => {
-                self.bccx.tcx.region_maps.encl_region(local_id)
+                ty::ReScope(self.bccx.tcx.region_maps.var_scope(local_id))
             }
             mc::cat_deref(_, _, mc::unsafe_ptr(..)) => {
                 ty::ReStatic
index b1337fca0c85da8f00849dfd05d0c5cb87d7e362..00e648db732e7ff05abbe58bbca660c2ca37c52b 100644 (file)
@@ -662,8 +662,9 @@ pub fn compute_kill_scope(&self, loan_scope: ast::NodeId, lp: @LoanPath)
         //! with immutable `&` pointers, because borrows of such pointers
         //! do not require restrictions and hence do not cause a loan.
 
-        let lexical_scope = self.bccx.tcx.region_maps.encl_scope(lp.node_id());
-        if self.bccx.tcx.region_maps.is_subscope_of(lexical_scope, loan_scope) {
+        let rm = &self.bccx.tcx.region_maps;
+        let lexical_scope = rm.var_scope(lp.node_id());
+        if rm.is_subscope_of(lexical_scope, loan_scope) {
             lexical_scope
         } else {
             assert!(self.bccx.tcx.region_maps.is_subscope_of(loan_scope, lexical_scope));
@@ -688,7 +689,7 @@ fn gather_fn_arg_patterns(&mut self,
             let arg_cmt = mc_ctxt.cat_rvalue(
                 arg.id,
                 arg.pat.span,
-                body.id, // Arguments live only as long as the fn body.
+                ty::ReScope(body.id), // Args live only as long as the fn body.
                 arg_ty);
 
             self.gather_pat(arg_cmt, arg.pat, None);
index e61ebd39ca766c666ad80283564ea311fdab1925..53cf5646cfb54fceca2986b3ab20ab16fd917fcc 100644 (file)
@@ -471,7 +471,7 @@ fn add_gen_kills(&self,
             for path in paths.get().iter() {
                 match *path.loan_path {
                     LpVar(id) => {
-                        let kill_id = tcx.region_maps.encl_scope(id);
+                        let kill_id = tcx.region_maps.var_scope(id);
                         let path = {
                             let path_map = self.path_map.borrow();
                             *path_map.get().get(&path.loan_path)
@@ -490,7 +490,7 @@ fn add_gen_kills(&self,
                     var_assignments.get().iter().enumerate() {
                 match *self.path_loan_path(assignment.path) {
                     LpVar(id) => {
-                        let kill_id = tcx.region_maps.encl_scope(id);
+                        let kill_id = tcx.region_maps.var_scope(id);
                         dfcx_assign.add_kill(kill_id, assignment_index);
                     }
                     LpExtend(..) => {
index 6da58c03b7247e3ab54927544132e6b78b14e47e..098e4154e17485861fe8344a2bde7ef1d829e295 100644 (file)
@@ -924,15 +924,16 @@ fn check_heap_item(cx: &Context, it: &ast::Item) {
     "allow", "deny", "forbid", "warn", // lint options
     "deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability
     "crate_map", "cfg", "doc", "export_name", "link_section", "no_freeze",
-    "no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag",
-    "packed", "simd", "repr", "deriving", "unsafe_destructor", "link",
+    "no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag", "packed",
+    "simd", "repr", "deriving", "unsafe_destructor", "link", "phase",
+    "macro_export",
 
     //mod-level
     "path", "link_name", "link_args", "nolink", "macro_escape", "no_implicit_prelude",
 
     // fn-level
     "test", "bench", "should_fail", "ignore", "inline", "lang", "main", "start",
-    "no_split_stack", "cold",
+    "no_split_stack", "cold", "macro_registrar",
 
     // internal attribute: bypass privacy inside items
     "!resolve_unexported",
index 65d2f9c150c84afcefddc009412e96f05914c630..e55229b37eba81053c3956e17d84aefeb7052828 100644 (file)
@@ -409,7 +409,7 @@ fn visit_fn(v: &mut LivenessVisitor,
     match *fk {
         visit::FkMethod(_, _, method) => {
             match method.explicit_self.node {
-                SelfValue(_) | SelfRegion(..) | SelfBox(_) | SelfUniq(_) => {
+                SelfValue(_) | SelfRegion(..) | SelfBox | SelfUniq(_) => {
                     fn_maps.add_variable(Arg(method.self_id,
                                              special_idents::self_));
                 }
index 8cf39d14763b395ec07cfee1f77693cc52d02777..70d4f63a16449942ce484033f1b95c347df2f00e 100644 (file)
@@ -60,7 +60,7 @@
 
 #[deriving(Eq)]
 pub enum categorization {
-    cat_rvalue(ast::NodeId),           // temporary val, argument is its scope
+    cat_rvalue(ty::Region),            // temporary val, argument is its scope
     cat_static_item,
     cat_copied_upvar(CopiedUpvar),     // upvar copied into @fn or ~fn env
     cat_stack_upvar(cmt),              // by ref upvar from ||
@@ -585,21 +585,26 @@ pub fn cat_def(&self,
     pub fn cat_rvalue_node<N:ast_node>(&self,
                                        node: &N,
                                        expr_ty: ty::t) -> cmt {
-        self.cat_rvalue(node.id(),
-                        node.span(),
-                        self.tcx.region_maps.cleanup_scope(node.id()),
-                        expr_ty)
+        match self.tcx.region_maps.temporary_scope(node.id()) {
+            Some(scope) => {
+                self.cat_rvalue(node.id(), node.span(),
+                                ty::ReScope(scope), expr_ty)
+            }
+            None => {
+                self.cat_rvalue(node.id(), node.span(), ty::ReStatic, expr_ty)
+            }
+        }
     }
 
     pub fn cat_rvalue(&self,
                       cmt_id: ast::NodeId,
                       span: Span,
-                      cleanup_scope_id: ast::NodeId,
+                      temp_scope: ty::Region,
                       expr_ty: ty::t) -> cmt {
         @cmt_ {
             id:cmt_id,
             span:span,
-            cat:cat_rvalue(cleanup_scope_id),
+            cat:cat_rvalue(temp_scope),
             mutbl:McDeclared,
             ty:expr_ty
         }
index 85217a7d55ece2d75ab5b1a69bdd70439a624b52..50096c012be3d073ec4580012b2ab0248fa6ff6b 100644 (file)
@@ -108,3 +108,14 @@ pub fn pat_contains_bindings(dm: resolve::DefMap, pat: &Pat) -> bool {
     });
     contains_bindings
 }
+
+pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> {
+    match pat.node {
+        PatIdent(BindByValue(_), ref path, None) => {
+            Some(path)
+        }
+        _ => {
+            None
+        }
+    }
+}
index ef755b12d15d18b9e11edc33dea2bbb59a18473e..c202684c7abff850b8bda193579a63158132bd70 100644 (file)
@@ -31,6 +31,7 @@
 use syntax::{ast, visit};
 use syntax::visit::{Visitor, FnKind};
 use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local};
+use syntax::ast_util::{stmt_id};
 
 /**
 The region maps encode information about region relationships.
   - the free region map is populated during type check as we check
     each function. See the function `relate_free_regions` for
     more information.
-- `cleanup_scopes` includes scopes where trans cleanups occur
-  - this is intended to reflect the current state of trans, not
-    necessarily how I think things ought to work
+- `temporary_scopes` includes scopes where cleanups for temporaries occur.
+  These are statements and loop/fn bodies.
 */
 pub struct RegionMaps {
     priv scope_map: RefCell<HashMap<ast::NodeId, ast::NodeId>>,
+    priv var_map: RefCell<HashMap<ast::NodeId, ast::NodeId>>,
     priv free_region_map: RefCell<HashMap<FreeRegion, ~[FreeRegion]>>,
-    priv cleanup_scopes: RefCell<HashSet<ast::NodeId>>,
+    priv rvalue_scopes: RefCell<HashMap<ast::NodeId, ast::NodeId>>,
+    priv terminating_scopes: RefCell<HashSet<ast::NodeId>>,
 }
 
 #[deriving(Clone)]
 pub struct Context {
-    // Scope where variables should be parented to
     var_parent: Option<ast::NodeId>,
 
     // Innermost enclosing expression
     parent: Option<ast::NodeId>,
 }
 
-struct RegionResolutionVisitor {
+struct RegionResolutionVisitor<'a> {
     sess: Session,
 
     // Generated maps:
-    region_maps: RegionMaps,
+    region_maps: &'a RegionMaps,
 }
 
 
@@ -91,22 +92,41 @@ pub fn relate_free_regions(&self, sub: FreeRegion, sup: FreeRegion) {
         free_region_map.get().insert(sub, ~[sup]);
     }
 
-    pub fn record_parent(&self, sub: ast::NodeId, sup: ast::NodeId) {
-        debug!("record_parent(sub={:?}, sup={:?})", sub, sup);
+    pub fn record_encl_scope(&self, sub: ast::NodeId, sup: ast::NodeId) {
+        debug!("record_encl_scope(sub={}, sup={})", sub, sup);
         assert!(sub != sup);
 
         let mut scope_map = self.scope_map.borrow_mut();
         scope_map.get().insert(sub, sup);
     }
 
-    pub fn record_cleanup_scope(&self, scope_id: ast::NodeId) {
-        //! Records that a scope is a CLEANUP SCOPE.  This is invoked
-        //! from within regionck.  We wait until regionck because we do
-        //! not know which operators are overloaded until that point,
-        //! and only overloaded operators result in cleanup scopes.
+    pub fn record_var_scope(&self, var: ast::NodeId, lifetime: ast::NodeId) {
+        debug!("record_var_scope(sub={}, sup={})", var, lifetime);
+        assert!(var != lifetime);
 
-        let mut cleanup_scopes = self.cleanup_scopes.borrow_mut();
-        cleanup_scopes.get().insert(scope_id);
+        let mut var_map = self.var_map.borrow_mut();
+        var_map.get().insert(var, lifetime);
+    }
+
+    pub fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: ast::NodeId) {
+        debug!("record_rvalue_scope(sub={}, sup={})", var, lifetime);
+        assert!(var != lifetime);
+
+        let mut rvalue_scopes = self.rvalue_scopes.borrow_mut();
+        rvalue_scopes.get().insert(var, lifetime);
+    }
+
+    pub fn mark_as_terminating_scope(&self, scope_id: ast::NodeId) {
+        /*!
+         * Records that a scope is a TERMINATING SCOPE. Whenever we
+         * create automatic temporaries -- e.g. by an
+         * expression like `a().f` -- they will be freed within
+         * the innermost terminating scope.
+         */
+
+        debug!("record_terminating_scope(scope_id={})", scope_id);
+        let mut terminating_scopes = self.terminating_scopes.borrow_mut();
+        terminating_scopes.get().insert(scope_id);
     }
 
     pub fn opt_encl_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
@@ -122,24 +142,51 @@ pub fn encl_scope(&self, id: ast::NodeId) -> ast::NodeId {
         let scope_map = self.scope_map.borrow();
         match scope_map.get().find(&id) {
             Some(&r) => r,
-            None => { fail!("No enclosing scope for id {:?}", id); }
+            None => { fail!("No enclosing scope for id {}", id); }
         }
     }
 
-    pub fn is_cleanup_scope(&self, scope_id: ast::NodeId) -> bool {
-        let cleanup_scopes = self.cleanup_scopes.borrow();
-        cleanup_scopes.get().contains(&scope_id)
+    pub fn var_scope(&self, var_id: ast::NodeId) -> ast::NodeId {
+        /*!
+         * Returns the lifetime of the local variable `var_id`
+         */
+
+        let var_map = self.var_map.borrow();
+        match var_map.get().find(&var_id) {
+            Some(&r) => r,
+            None => { fail!("No enclosing scope for id {}", var_id); }
+        }
     }
 
-    pub fn cleanup_scope(&self, expr_id: ast::NodeId) -> ast::NodeId {
-        //! Returns the scope when temps in expr will be cleaned up
+    pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<ast::NodeId> {
+        //! Returns the scope when temp created by expr_id will be cleaned up
+
+        // check for a designated rvalue scope
+        let rvalue_scopes = self.rvalue_scopes.borrow();
+        match rvalue_scopes.get().find(&expr_id) {
+            Some(&s) => {
+                debug!("temporary_scope({}) = {} [custom]", expr_id, s);
+                return Some(s);
+            }
+            None => { }
+        }
 
+        // else, locate the innermost terminating scope
         let mut id = self.encl_scope(expr_id);
-        let cleanup_scopes = self.cleanup_scopes.borrow();
-        while !cleanup_scopes.get().contains(&id) {
-            id = self.encl_scope(id);
+        let terminating_scopes = self.terminating_scopes.borrow();
+        while !terminating_scopes.get().contains(&id) {
+            match self.opt_encl_scope(id) {
+                Some(p) => {
+                    id = p;
+                }
+                None => {
+                    debug!("temporary_scope({}) = None", expr_id);
+                    return None;
+                }
+            }
         }
-        return id;
+        debug!("temporary_scope({}) = {} [enclosing]", expr_id, id);
+        return Some(id);
     }
 
     pub fn encl_region(&self, id: ast::NodeId) -> ty::Region {
@@ -148,6 +195,12 @@ pub fn encl_region(&self, id: ast::NodeId) -> ty::Region {
         ty::ReScope(self.encl_scope(id))
     }
 
+    pub fn var_region(&self, id: ast::NodeId) -> ty::Region {
+        //! Returns the lifetime of the variable `id`.
+
+        ty::ReScope(self.var_scope(id))
+    }
+
     pub fn scopes_intersect(&self, scope1: ast::NodeId, scope2: ast::NodeId)
                             -> bool {
         self.is_subscope_of(scope1, scope2) ||
@@ -168,7 +221,7 @@ pub fn is_subscope_of(&self,
             let scope_map = self.scope_map.borrow();
             match scope_map.get().find(&s) {
                 None => {
-                    debug!("is_subscope_of({:?}, {:?}, s={:?})=false",
+                    debug!("is_subscope_of({}, {}, s={})=false",
                            subscope, superscope, s);
 
                     return false;
@@ -177,7 +230,7 @@ pub fn is_subscope_of(&self,
             }
         }
 
-        debug!("is_subscope_of({:?}, {:?})=true",
+        debug!("is_subscope_of({}, {})=true",
                subscope, superscope);
 
         return true;
@@ -323,67 +376,138 @@ fn ancestors_of(this: &RegionMaps, scope: ast::NodeId)
 }
 
 /// Records the current parent (if any) as the parent of `child_id`.
-fn parent_to_expr(visitor: &mut RegionResolutionVisitor,
-                  cx: Context, child_id: ast::NodeId, sp: Span) {
-    debug!("region::parent_to_expr(span={:?})",
-           visitor.sess.codemap.span_to_str(sp));
-    for parent_id in cx.parent.iter() {
-        visitor.region_maps.record_parent(child_id, *parent_id);
+fn record_superlifetime(visitor: &mut RegionResolutionVisitor,
+                        cx: Context,
+                        child_id: ast::NodeId,
+                        _sp: Span) {
+    for &parent_id in cx.parent.iter() {
+        visitor.region_maps.record_encl_scope(child_id, parent_id);
+    }
+}
+
+/// Records the lifetime of a local variable as `cx.var_parent`
+fn record_var_lifetime(visitor: &mut RegionResolutionVisitor,
+                       cx: Context,
+                       var_id: ast::NodeId,
+                       _sp: Span) {
+    match cx.var_parent {
+        Some(parent_id) => {
+            visitor.region_maps.record_var_scope(var_id, parent_id);
+        }
+        None => {
+            // this can happen in extern fn declarations like
+            //
+            // extern fn isalnum(c: c_int) -> c_int
+        }
     }
 }
 
 fn resolve_block(visitor: &mut RegionResolutionVisitor,
                  blk: &ast::Block,
                  cx: Context) {
-    // Record the parent of this block.
-    parent_to_expr(visitor, cx, blk.id, blk.span);
+    debug!("resolve_block(blk.id={})", blk.id);
 
-    // Descend.
-    let new_cx = Context {var_parent: Some(blk.id),
-                          parent: Some(blk.id)};
-    visit::walk_block(visitor, blk, new_cx);
+    // Record the parent of this block.
+    record_superlifetime(visitor, cx, blk.id, blk.span);
+
+    // We treat the tail expression in the block (if any) somewhat
+    // differently from the statements. The issue has to do with
+    // temporary lifetimes. If the user writes:
+    //
+    //   {
+    //     ... (&foo()) ...
+    //   }
+    //
+
+    let subcx = Context {var_parent: Some(blk.id), parent: Some(blk.id)};
+    visit::walk_block(visitor, blk, subcx);
 }
 
 fn resolve_arm(visitor: &mut RegionResolutionVisitor,
                arm: &ast::Arm,
                cx: Context) {
+    visitor.region_maps.mark_as_terminating_scope(arm.body.id);
+
+    match arm.guard {
+        Some(expr) => {
+            visitor.region_maps.mark_as_terminating_scope(expr.id);
+        }
+        None => { }
+    }
+
     visit::walk_arm(visitor, arm, cx);
 }
 
 fn resolve_pat(visitor: &mut RegionResolutionVisitor,
                pat: &ast::Pat,
                cx: Context) {
-    assert_eq!(cx.var_parent, cx.parent);
-    parent_to_expr(visitor, cx, pat.id, pat.span);
+    record_superlifetime(visitor, cx, pat.id, pat.span);
+
+    // If this is a binding (or maybe a binding, I'm too lazy to check
+    // the def map) then record the lifetime of that binding.
+    match pat.node {
+        ast::PatIdent(..) => {
+            record_var_lifetime(visitor, cx, pat.id, pat.span);
+        }
+        _ => { }
+    }
+
     visit::walk_pat(visitor, pat, cx);
 }
 
 fn resolve_stmt(visitor: &mut RegionResolutionVisitor,
                 stmt: &ast::Stmt,
                 cx: Context) {
-    match stmt.node {
-        ast::StmtDecl(..) => {
-            visit::walk_stmt(visitor, stmt, cx);
-        }
-        ast::StmtExpr(_, stmt_id) |
-        ast::StmtSemi(_, stmt_id) => {
-            parent_to_expr(visitor, cx, stmt_id, stmt.span);
-            let expr_cx = Context {parent: Some(stmt_id), ..cx};
-            visit::walk_stmt(visitor, stmt, expr_cx);
-        }
-        ast::StmtMac(..) => visitor.sess.bug("unexpanded macro")
-    }
+    let stmt_id = stmt_id(stmt);
+    debug!("resolve_stmt(stmt.id={})", stmt_id);
+
+    visitor.region_maps.mark_as_terminating_scope(stmt_id);
+    record_superlifetime(visitor, cx, stmt_id, stmt.span);
+
+    let subcx = Context {parent: Some(stmt_id), ..cx};
+    visit::walk_stmt(visitor, stmt, subcx);
 }
 
 fn resolve_expr(visitor: &mut RegionResolutionVisitor,
                 expr: &ast::Expr,
                 cx: Context) {
-    parent_to_expr(visitor, cx, expr.id, expr.span);
+    debug!("resolve_expr(expr.id={})", expr.id);
+
+    record_superlifetime(visitor, cx, expr.id, expr.span);
 
     let mut new_cx = cx;
     new_cx.parent = Some(expr.id);
     match expr.node {
-        ast::ExprAssignOp(..) | ast::ExprIndex(..) | ast::ExprBinary(..) |
+        // Conditional or repeating scopes are always terminating
+        // scopes, meaning that temporaries cannot outlive them.
+        // This ensures fixed size stacks.
+
+        ast::ExprBinary(_, ast::BiAnd, _, r) |
+        ast::ExprBinary(_, ast::BiOr, _, r) => {
+            // For shortcircuiting operators, mark the RHS as a terminating
+            // scope since it only executes conditionally.
+            visitor.region_maps.mark_as_terminating_scope(r.id);
+        }
+
+        ast::ExprIf(_, then, Some(otherwise)) => {
+            visitor.region_maps.mark_as_terminating_scope(then.id);
+            visitor.region_maps.mark_as_terminating_scope(otherwise.id);
+        }
+
+        ast::ExprIf(_, then, None) => {
+            visitor.region_maps.mark_as_terminating_scope(then.id);
+        }
+
+        ast::ExprLoop(body, _) |
+        ast::ExprWhile(_, body) => {
+            visitor.region_maps.mark_as_terminating_scope(body.id);
+        }
+
+        ast::ExprMatch(..) => {
+            new_cx.var_parent = Some(expr.id);
+        }
+
+        ast::ExprAssignOp(..) | ast::ExprIndex(..) |
         ast::ExprUnary(..) | ast::ExprCall(..) | ast::ExprMethodCall(..) => {
             // FIXME(#6268) Nested method calls
             //
@@ -402,11 +526,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor,
             // for an extended explanantion of why this distinction is
             // important.
             //
-            // parent_to_expr(new_cx, expr.callee_id);
-        }
-
-        ast::ExprMatch(..) => {
-            new_cx.var_parent = Some(expr.id);
+            // record_superlifetime(new_cx, expr.callee_id);
         }
 
         _ => {}
@@ -419,9 +539,256 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor,
 fn resolve_local(visitor: &mut RegionResolutionVisitor,
                  local: &ast::Local,
                  cx: Context) {
-    assert_eq!(cx.var_parent, cx.parent);
-    parent_to_expr(visitor, cx, local.id, local.span);
+    debug!("resolve_local(local.id={},local.init={})",
+           local.id,local.init.is_some());
+
+    let blk_id = match cx.var_parent {
+        Some(id) => id,
+        None => {
+            visitor.sess.span_bug(
+                local.span,
+                "Local without enclosing block");
+        }
+    };
+
+    // For convenience in trans, associate with the local-id the var
+    // scope that will be used for any bindings declared in this
+    // pattern.
+    visitor.region_maps.record_var_scope(local.id, blk_id);
+
+    // As an exception to the normal rules governing temporary
+    // lifetimes, initializers in a let have a temporary lifetime
+    // of the enclosing block. This means that e.g. a program
+    // like the following is legal:
+    //
+    //     let ref x = HashMap::new();
+    //
+    // Because the hash map will be freed in the enclosing block.
+    //
+    // We express the rules more formally based on 3 grammars (defined
+    // fully in the helpers below that implement them):
+    //
+    // 1. `E&`, which matches expressions like `&<rvalue>` that
+    //    own a pointer into the stack.
+    //
+    // 2. `P&`, which matches patterns like `ref x` or `(ref x, ref
+    //    y)` that produce ref bindings into the value they are
+    //    matched against or something (at least partially) owned by
+    //    the value they are matched against. (By partially owned,
+    //    I mean that creating a binding into a ref-counted or managed value
+    //    would still count.)
+    //
+    // 3. `ET`, which matches both rvalues like `foo()` as well as lvalues
+    //    based on rvalues like `foo().x[2].y`.
+    //
+    // A subexpression `<rvalue>` that appears in a let initializer
+    // `let pat [: ty] = expr` has an extended temporary lifetime if
+    // any of the following conditions are met:
+    //
+    // A. `pat` matches `P&` and `expr` matches `ET`
+    //    (covers cases where `pat` creates ref bindings into an rvalue
+    //     produced by `expr`)
+    // B. `ty` is a borrowed pointer and `expr` matches `ET`
+    //    (covers cases where coercion creates a borrow)
+    // C. `expr` matches `E&`
+    //    (covers cases `expr` borrows an rvalue that is then assigned
+    //     to memory (at least partially) owned by the binding)
+    //
+    // Here are some examples hopefully giving an intution where each
+    // rule comes into play and why:
+    //
+    // Rule A. `let (ref x, ref y) = (foo().x, 44)`. The rvalue `(22, 44)`
+    // would have an extended lifetime, but not `foo()`.
+    //
+    // Rule B. `let x: &[...] = [foo().x]`. The rvalue `[foo().x]`
+    // would have an extended lifetime, but not `foo()`.
+    //
+    // Rule C. `let x = &foo().x`. The rvalue ``foo()` would have extended
+    // lifetime.
+    //
+    // In some cases, multiple rules may apply (though not to the same
+    // rvalue). For example:
+    //
+    //     let ref x = [&a(), &b()];
+    //
+    // Here, the expression `[...]` has an extended lifetime due to rule
+    // A, but the inner rvalues `a()` and `b()` have an extended lifetime
+    // due to rule C.
+    //
+    // FIXME(#6308) -- Note that `[]` patterns work more smoothly post-DST.
+
+    match local.init {
+        Some(expr) => {
+            record_rvalue_scope_if_borrow_expr(visitor, expr, blk_id);
+
+            if is_binding_pat(local.pat) || is_borrowed_ty(local.ty) {
+                record_rvalue_scope(visitor, expr, blk_id);
+            }
+        }
+
+        None => { }
+    }
+
     visit::walk_local(visitor, local, cx);
+
+    fn is_binding_pat(pat: &ast::Pat) -> bool {
+        /*!
+         * True if `pat` match the `P&` nonterminal:
+         *
+         *     P& = ref X
+         *        | StructName { ..., P&, ... }
+         *        | VariantName(..., P&, ...)
+         *        | [ ..., P&, ... ]
+         *        | ( ..., P&, ... )
+         *        | ~P&
+         *        | box P&
+         */
+
+        match pat.node {
+            ast::PatIdent(ast::BindByRef(_), _, _) => true,
+
+            ast::PatStruct(_, ref field_pats, _) => {
+                field_pats.iter().any(|fp| is_binding_pat(fp.pat))
+            }
+
+            ast::PatVec(ref pats1, ref pats2, ref pats3) => {
+                pats1.iter().any(|&p| is_binding_pat(p)) ||
+                pats2.iter().any(|&p| is_binding_pat(p)) ||
+                pats3.iter().any(|&p| is_binding_pat(p))
+            }
+
+            ast::PatEnum(_, Some(ref subpats)) |
+            ast::PatTup(ref subpats) => {
+                subpats.iter().any(|&p| is_binding_pat(p))
+            }
+
+            ast::PatUniq(subpat) => {
+                is_binding_pat(subpat)
+            }
+
+            _ => false,
+        }
+    }
+
+    fn is_borrowed_ty(ty: &ast::Ty) -> bool {
+        /*!
+         * True if `ty` is a borrowed pointer type
+         * like `&int` or `&[...]`.
+         */
+
+        match ty.node {
+            ast::TyRptr(..) => true,
+            _ => false
+        }
+    }
+
+    fn record_rvalue_scope_if_borrow_expr(visitor: &mut RegionResolutionVisitor,
+                                          expr: &ast::Expr,
+                                          blk_id: ast::NodeId) {
+        /*!
+         * If `expr` matches the `E&` grammar, then records an extended
+         * rvalue scope as appropriate:
+         *
+         *     E& = & ET
+         *        | StructName { ..., f: E&, ... }
+         *        | [ ..., E&, ... ]
+         *        | ( ..., E&, ... )
+         *        | {...; E&}
+         *        | ~E&
+         *        | E& as ...
+         *        | ( E& )
+         */
+
+        match expr.node {
+            ast::ExprAddrOf(_, subexpr) => {
+                record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
+                record_rvalue_scope(visitor, subexpr, blk_id);
+            }
+            ast::ExprStruct(_, ref fields, _) => {
+                for field in fields.iter() {
+                    record_rvalue_scope_if_borrow_expr(
+                        visitor, field.expr, blk_id);
+                }
+            }
+            ast::ExprVstore(subexpr, _) => {
+                visitor.region_maps.record_rvalue_scope(subexpr.id, blk_id);
+                record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
+            }
+            ast::ExprVec(ref subexprs, _) |
+            ast::ExprTup(ref subexprs) => {
+                for &subexpr in subexprs.iter() {
+                    record_rvalue_scope_if_borrow_expr(
+                        visitor, subexpr, blk_id);
+                }
+            }
+            ast::ExprUnary(_, ast::UnUniq, subexpr) => {
+                record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
+            }
+            ast::ExprCast(subexpr, _) |
+            ast::ExprParen(subexpr) => {
+                record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id)
+            }
+            ast::ExprBlock(ref block) => {
+                match block.expr {
+                    Some(subexpr) => {
+                        record_rvalue_scope_if_borrow_expr(
+                            visitor, subexpr, blk_id);
+                    }
+                    None => { }
+                }
+            }
+            _ => {
+            }
+        }
+    }
+
+    fn record_rvalue_scope<'a>(visitor: &mut RegionResolutionVisitor,
+                               expr: &'a ast::Expr,
+                               blk_id: ast::NodeId) {
+        /*!
+         * Applied to an expression `expr` if `expr` -- or something
+         * owned or partially owned by `expr` -- is going to be
+         * indirectly referenced by a variable in a let statement. In
+         * that case, the "temporary lifetime" or `expr` is extended
+         * to be the block enclosing the `let` statement.
+         *
+         * More formally, if `expr` matches the grammar `ET`, record
+         * the rvalue scope of the matching `<rvalue>` as `blk_id`:
+         *
+         *     ET = *ET
+         *        | ET[...]
+         *        | ET.f
+         *        | (ET)
+         *        | <rvalue>
+         *
+         * Note: ET is intended to match "rvalues or
+         * lvalues based on rvalues".
+         */
+
+        let mut expr = expr;
+        loop {
+            // Note: give all the expressions matching `ET` with the
+            // extended temporary lifetime, not just the innermost rvalue,
+            // because in trans if we must compile e.g. `*rvalue()`
+            // into a temporary, we request the temporary scope of the
+            // outer expression.
+            visitor.region_maps.record_rvalue_scope(expr.id, blk_id);
+
+            match expr.node {
+                ast::ExprAddrOf(_, ref subexpr) |
+                ast::ExprUnary(_, ast::UnDeref, ref subexpr) |
+                ast::ExprField(ref subexpr, _, _) |
+                ast::ExprIndex(_, ref subexpr, _) |
+                ast::ExprParen(ref subexpr) => {
+                    let subexpr: &'a @Expr = subexpr; // FIXME(#11586)
+                    expr = &**subexpr;
+                }
+                _ => {
+                    return;
+                }
+            }
+        }
+    }
 }
 
 fn resolve_item(visitor: &mut RegionResolutionVisitor,
@@ -439,22 +806,23 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
               sp: Span,
               id: ast::NodeId,
               cx: Context) {
-    debug!("region::resolve_fn(id={:?}, \
+    debug!("region::resolve_fn(id={}, \
                                span={:?}, \
-                               body.id={:?}, \
-                               cx.parent={:?})",
+                               body.id={}, \
+                               cx.parent={})",
            id,
            visitor.sess.codemap.span_to_str(sp),
            body.id,
            cx.parent);
 
+    visitor.region_maps.mark_as_terminating_scope(body.id);
+
     // The arguments and `self` are parented to the body of the fn.
     let decl_cx = Context {parent: Some(body.id),
-                           var_parent: Some(body.id),
-                           ..cx};
+                           var_parent: Some(body.id)};
     match *fk {
         visit::FkMethod(_, _, method) => {
-            visitor.region_maps.record_parent(method.self_id, body.id);
+            visitor.region_maps.record_var_scope(method.self_id, body.id);
         }
         _ => {}
     }
@@ -471,7 +839,7 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
     visitor.visit_block(body, body_cx);
 }
 
-impl Visitor<Context> for RegionResolutionVisitor {
+impl<'a> Visitor<Context> for RegionResolutionVisitor<'a> {
 
     fn visit_block(&mut self, b: &Block, cx: Context) {
         resolve_block(self, b, cx);
@@ -503,16 +871,33 @@ fn visit_local(&mut self, l: &Local, cx: Context) {
 }
 
 pub fn resolve_crate(sess: Session, crate: &ast::Crate) -> RegionMaps {
+    let maps = RegionMaps {
+        scope_map: RefCell::new(HashMap::new()),
+        var_map: RefCell::new(HashMap::new()),
+        free_region_map: RefCell::new(HashMap::new()),
+        rvalue_scopes: RefCell::new(HashMap::new()),
+        terminating_scopes: RefCell::new(HashSet::new()),
+    };
+    {
+        let mut visitor = RegionResolutionVisitor {
+            sess: sess,
+            region_maps: &maps
+        };
+        let cx = Context { parent: None, var_parent: None };
+        visit::walk_crate(&mut visitor, crate, cx);
+    }
+    return maps;
+}
+
+pub fn resolve_inlined_item(sess: Session,
+                            region_maps: &RegionMaps,
+                            item: &ast::InlinedItem) {
+    let cx = Context {parent: None,
+                      var_parent: None};
     let mut visitor = RegionResolutionVisitor {
         sess: sess,
-        region_maps: RegionMaps {
-            scope_map: RefCell::new(HashMap::new()),
-            free_region_map: RefCell::new(HashMap::new()),
-            cleanup_scopes: RefCell::new(HashSet::new())
-        }
+        region_maps: region_maps,
     };
-    let cx = Context { parent: None, var_parent: None };
-    visit::walk_crate(&mut visitor, crate, cx);
-    return visitor.region_maps;
+    visit::walk_inlined_item(&mut visitor, item, cx);
 }
 
index 8731bf07ec3d2ce5f2b27d8f1f4ae00cdd86db78..e42f4433653d312d222435005043b5e838491dba 100644 (file)
@@ -1400,10 +1400,7 @@ fn build_reduced_graph_for_item(&mut self,
                 name_bindings.define_type(DefTrait(def_id), sp, is_public);
                 new_parent
             }
-
-            ItemMac(..) => {
-                fail!("item macros unimplemented")
-            }
+            ItemMac(..) => parent
         }
     }
 
@@ -2442,7 +2439,7 @@ fn get_binding(this: &mut Resolver,
         match type_result {
             BoundResult(target_module, name_bindings) => {
                 debug!("(resolving single import) found type target: {:?}",
-                        name_bindings.type_def.get().unwrap().type_def);
+                       {name_bindings.type_def.get().unwrap().type_def});
                 import_resolution.type_target.set(
                     Some(Target::new(target_module, name_bindings)));
                 import_resolution.type_id.set(directive.id);
@@ -3804,9 +3801,9 @@ fn resolve_item(&mut self, item: &Item) {
                 });
             }
 
-            ItemMac(..) => {
-                fail!("item macros unimplemented")
-            }
+           ItemMac(..) => {
+                // do nothing, these are just around to be encoded
+           }
         }
     }
 
index aa2bd656b909168e3edf4beadbf28e6220f66519..96367c769fdbfa2f1061c93c84206e44fa8f3bce 100644 (file)
 use middle::trans::base::*;
 use middle::trans::build::*;
 use middle::trans::callee;
+use middle::trans::cleanup;
+use middle::trans::cleanup::CleanupMethods;
 use middle::trans::common::*;
 use middle::trans::consts;
 use middle::trans::controlflow;
 
 use std::cell::Cell;
 use std::hashmap::HashMap;
-use std::ptr;
 use std::vec;
 use syntax::ast;
 use syntax::ast::Ident;
@@ -315,16 +316,18 @@ pub enum opt_result<'a> {
 fn trans_opt<'a>(bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
     let _icx = push_ctxt("match::trans_opt");
     let ccx = bcx.ccx();
-    let bcx = bcx;
+    let mut bcx = bcx;
     match *o {
         lit(ExprLit(lit_expr)) => {
-            let datumblock = expr::trans_to_datum(bcx, lit_expr);
-            return single_result(datumblock.to_result());
+            let lit_datum = unpack_datum!(bcx, expr::trans(bcx, lit_expr));
+            let lit_datum = lit_datum.assert_rvalue(bcx); // literals are rvalues
+            let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
+            return single_result(rslt(bcx, lit_datum.val));
         }
         lit(UnitLikeStructLit(pat_id)) => {
             let struct_ty = ty::node_id_to_type(bcx.tcx(), pat_id);
-            let datumblock = datum::scratch_datum(bcx, struct_ty, "", true);
-            return single_result(datumblock.to_result(bcx));
+            let datum = datum::rvalue_scratch_datum(bcx, struct_ty, "");
+            return single_result(rslt(bcx, datum.val));
         }
         lit(ConstLit(lit_id)) => {
             let (llval, _) = consts::get_const_val(bcx.ccx(), lit_id);
@@ -1007,14 +1010,18 @@ fn extract_variant_args<'a>(
     ExtractedBlock { vals: args, bcx: bcx }
 }
 
-fn match_datum<'a>(bcx: &'a Block<'a>, val: ValueRef, pat_id: ast::NodeId)
-               -> Datum {
-    //! Helper for converting from the ValueRef that we pass around in
-    //! the match code, which is always by ref, into a Datum. Eventually
-    //! we should just pass around a Datum and be done with it.
+fn match_datum(bcx: &Block,
+               val: ValueRef,
+               pat_id: ast::NodeId)
+               -> Datum<Lvalue> {
+    /*!
+     * Helper for converting from the ValueRef that we pass around in
+     * the match code, which is always an lvalue, into a Datum. Eventually
+     * we should just pass around a Datum and be done with it.
+     */
 
     let ty = node_id_type(bcx, pat_id);
-    Datum {val: val, ty: ty, mode: datum::ByRef(RevokeClean)}
+    Datum(val, ty, Lvalue)
 }
 
 
@@ -1054,13 +1061,11 @@ fn extract_vec_elems<'a>(
             ty::mt {ty: vt.unit_ty, mutbl: ast::MutImmutable},
             ty::vstore_slice(ty::ReStatic)
         );
-        let scratch = scratch_datum(bcx, slice_ty, "", false);
+        let scratch = rvalue_scratch_datum(bcx, slice_ty, "");
         Store(bcx, slice_begin,
-            GEPi(bcx, scratch.val, [0u, abi::slice_elt_base])
-        );
+              GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
         Store(bcx, slice_len, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
         elems[n] = scratch.val;
-        scratch.add_clean(bcx);
     }
 
     ExtractedBlock { vals: elems, bcx: bcx }
@@ -1176,7 +1181,8 @@ fn handle_fail(&self) -> BasicBlockRef {
             _ => (),
         }
 
-        let fail_cx = sub_block(self.bcx, "case_fallthrough");
+        let fcx = self.bcx.fcx;
+        let fail_cx = fcx.new_block(false, "case_fallthrough", None);
         controlflow::trans_fail(fail_cx, Some(self.sp), self.msg);
         self.finished.set(Some(fail_cx.llbb));
         fail_cx.llbb
@@ -1297,30 +1303,31 @@ fn compare_values<'a>(
 fn store_non_ref_bindings<'a>(
                           bcx: &'a Block<'a>,
                           bindings_map: &BindingsMap,
-                          mut opt_temp_cleanups: Option<&mut ~[ValueRef]>)
-                          -> &'a Block<'a> {
+                          opt_cleanup_scope: Option<cleanup::ScopeId>)
+                          -> &'a Block<'a>
+{
     /*!
-     *
-     * For each copy/move binding, copy the value from the value
-     * being matched into its final home.  This code executes once
-     * one of the patterns for a given arm has completely matched.
-     * It adds temporary cleanups to the `temp_cleanups` array,
-     * if one is provided.
+     * For each copy/move binding, copy the value from the value being
+     * matched into its final home.  This code executes once one of
+     * the patterns for a given arm has completely matched.  It adds
+     * cleanups to the `opt_cleanup_scope`, if one is provided.
      */
 
+    let fcx = bcx.fcx;
     let mut bcx = bcx;
     for (_, &binding_info) in bindings_map.iter() {
         match binding_info.trmode {
             TrByValue(lldest) => {
                 let llval = Load(bcx, binding_info.llmatch); // get a T*
-                let datum = Datum {val: llval, ty: binding_info.ty,
-                                   mode: ByRef(ZeroMem)};
-                bcx = datum.store_to(bcx, INIT, lldest);
-                opt_temp_cleanups.mutate(|temp_cleanups| {
-                    add_clean_temp_mem(bcx, lldest, binding_info.ty);
-                    temp_cleanups.push(lldest);
-                    temp_cleanups
-                });
+                let datum = Datum(llval, binding_info.ty, Lvalue);
+                bcx = datum.store_to(bcx, lldest);
+
+                match opt_cleanup_scope {
+                    None => {}
+                    Some(s) => {
+                        fcx.schedule_drop_mem(s, lldest, binding_info.ty);
+                    }
+                }
             }
             TrByRef => {}
         }
@@ -1328,38 +1335,29 @@ fn store_non_ref_bindings<'a>(
     return bcx;
 }
 
-fn insert_lllocals<'a>(
-                   bcx: &'a Block<'a>,
-                   bindings_map: &BindingsMap,
-                   add_cleans: bool)
-                   -> &'a Block<'a> {
+fn insert_lllocals<'a>(bcx: &'a Block<'a>,
+                       bindings_map: &BindingsMap,
+                       cleanup_scope: cleanup::ScopeId)
+                       -> &'a Block<'a> {
     /*!
      * For each binding in `data.bindings_map`, adds an appropriate entry into
-     * the `fcx.lllocals` map.  If add_cleans is true, then adds cleanups for
-     * the bindings.
+     * the `fcx.lllocals` map, scheduling cleanup in `cleanup_scope`.
      */
 
+    let fcx = bcx.fcx;
+
     for (&ident, &binding_info) in bindings_map.iter() {
         let llval = match binding_info.trmode {
             // By value bindings: use the stack slot that we
             // copied/moved the value into
             TrByValue(lldest) => lldest,
+
             // By ref binding: use the ptr into the matched value
             TrByRef => binding_info.llmatch
         };
 
-        let datum = Datum {
-            val: llval,
-            ty: binding_info.ty,
-            mode: ByRef(ZeroMem)
-        };
-
-        if add_cleans {
-            match binding_info.trmode {
-                TrByValue(_) => datum.add_clean(bcx),
-                _ => {}
-            }
-        }
+        let datum = Datum(llval, binding_info.ty, Lvalue);
+        fcx.schedule_drop_mem(cleanup_scope, llval, binding_info.ty);
 
         {
             debug!("binding {:?} to {}",
@@ -1396,24 +1394,23 @@ fn compile_guard<'r,
            vec_map_to_str(vals, |v| bcx.val_to_str(*v)));
     let _indenter = indenter();
 
+    // Lest the guard itself should fail, introduce a temporary cleanup
+    // scope for any non-ref bindings we create.
+    let temp_scope = bcx.fcx.push_custom_cleanup_scope();
+
     let mut bcx = bcx;
-    let mut temp_cleanups = ~[];
-    bcx = store_non_ref_bindings(bcx,
-                                 data.bindings_map,
-                                 Some(&mut temp_cleanups));
-    bcx = insert_lllocals(bcx, data.bindings_map, false);
-
-    let val = unpack_result!(bcx, {
-        with_scope_result(bcx, guard_expr.info(), "guard", |bcx| {
-            expr::trans_to_datum(bcx, guard_expr).to_result()
-        })
-    });
-    let val = bool_to_i1(bcx, val);
+    bcx = store_non_ref_bindings(bcx, data.bindings_map,
+                                 Some(cleanup::CustomScope(temp_scope)));
+    bcx = insert_lllocals(bcx, data.bindings_map,
+                          cleanup::CustomScope(temp_scope));
 
-    // Revoke the temp cleanups now that the guard successfully executed.
-    for llval in temp_cleanups.iter() {
-        revoke_clean(bcx, *llval);
-    }
+    let val = unpack_datum!(bcx, expr::trans(bcx, guard_expr));
+    let val = val.to_llbool(bcx);
+
+    // Cancel cleanups now that the guard successfully executed.  If
+    // the guard was false, we will drop the values explicitly
+    // below. Otherwise, we'll add lvalue cleanups at the end.
+    bcx.fcx.pop_custom_cleanup_scope(temp_scope);
 
     return with_cond(bcx, Not(bcx, val), |bcx| {
         // Guard does not match: free the values we copied,
@@ -1502,6 +1499,7 @@ fn compile_submatch_continue<'r,
                              chk: &FailureHandler,
                              col: uint,
                              val: ValueRef) {
+    let fcx = bcx.fcx;
     let tcx = bcx.tcx();
     let dm = tcx.def_map;
 
@@ -1584,14 +1582,9 @@ fn compile_submatch_continue<'r,
     }
 
     if any_uniq_pat(m, col) {
-        let pat_ty = node_id_type(bcx, pat_id);
         let llbox = Load(bcx, val);
-        let unboxed = match ty::get(pat_ty).sty {
-            ty::ty_uniq(..) if !ty::type_contents(bcx.tcx(), pat_ty).owns_managed() => llbox,
-            _ => GEPi(bcx, llbox, [0u, abi::box_field_body])
-        };
         compile_submatch(bcx, enter_uniq(bcx, dm, m, col, val),
-                         vec::append(~[unboxed], vals_left), chk);
+                         vec::append(~[llbox], vals_left), chk);
         return;
     }
 
@@ -1607,6 +1600,7 @@ fn compile_submatch_continue<'r,
     debug!("options={:?}", opts);
     let mut kind = no_branch;
     let mut test_val = val;
+    debug!("test_val={}", bcx.val_to_str(test_val));
     if opts.len() > 0u {
         match opts[0] {
             var(_, repr) => {
@@ -1626,8 +1620,7 @@ fn compile_submatch_continue<'r,
             },
             vec_len(..) => {
                 let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
-                let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
-                let (_, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty);
+                let (_, len) = tvec::get_base_and_len(bcx, val, vt.vec_ty);
                 test_val = len;
                 kind = compare_vec_len;
             }
@@ -1641,7 +1634,7 @@ fn compile_submatch_continue<'r,
     }
     let else_cx = match kind {
         no_branch | single => bcx,
-        _ => sub_block(bcx, "match_else")
+        _ => bcx.fcx.new_temp_block("match_else")
     };
     let sw = if kind == switch {
         Switch(bcx, test_val, else_cx.llbb, opts.len())
@@ -1662,7 +1655,7 @@ fn compile_submatch_continue<'r,
         let mut branch_chk = None;
         let mut opt_cx = else_cx;
         if !exhaustive || i+1 < len {
-            opt_cx = sub_block(bcx, "match_case");
+            opt_cx = bcx.fcx.new_temp_block("match_case");
             match kind {
               single => Br(bcx, opt_cx.llbb),
               switch => {
@@ -1683,75 +1676,65 @@ fn compile_submatch_continue<'r,
               compare => {
                   let t = node_id_type(bcx, pat_id);
                   let Result {bcx: after_cx, val: matches} = {
-                      with_scope_result(bcx, None, "compaReScope", |bcx| {
-                          match trans_opt(bcx, opt) {
-                              single_result(
-                                  Result {bcx, val}) => {
-                                  compare_values(bcx, test_val, val, t)
-                              }
-                              lower_bound(
-                                  Result {bcx, val}) => {
+                      match trans_opt(bcx, opt) {
+                          single_result(Result {bcx, val}) => {
+                              compare_values(bcx, test_val, val, t)
+                          }
+                          lower_bound(Result {bcx, val}) => {
+                              compare_scalar_types(
+                                  bcx, test_val, val,
+                                  t, ast::BiGe)
+                          }
+                          range_result(Result {val: vbegin, ..},
+                                       Result {bcx, val: vend}) => {
+                              let Result {bcx, val: llge} =
                                   compare_scalar_types(
-                                          bcx, test_val, val,
-                                          t, ast::BiGe)
-                              }
-                              range_result(
-                                  Result {val: vbegin, ..},
-                                  Result {bcx, val: vend}) => {
-                                  let Result {bcx, val: llge} =
-                                      compare_scalar_types(
-                                          bcx, test_val,
-                                          vbegin, t, ast::BiGe);
-                                  let Result {bcx, val: llle} =
-                                      compare_scalar_types(
-                                          bcx, test_val, vend,
-                                          t, ast::BiLe);
-                                  rslt(bcx, And(bcx, llge, llle))
-                              }
+                                  bcx, test_val,
+                                  vbegin, t, ast::BiGe);
+                              let Result {bcx, val: llle} =
+                                  compare_scalar_types(
+                                  bcx, test_val, vend,
+                                  t, ast::BiLe);
+                              rslt(bcx, And(bcx, llge, llle))
                           }
-                      })
+                      }
                   };
-                  bcx = sub_block(after_cx, "compare_next");
+                  bcx = fcx.new_temp_block("compare_next");
                   CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
               }
               compare_vec_len => {
                   let Result {bcx: after_cx, val: matches} = {
-                      with_scope_result(bcx,
-                                        None,
-                                        "compare_vec_len_scope",
-                                        |bcx| {
-                          match trans_opt(bcx, opt) {
-                              single_result(
-                                  Result {bcx, val}) => {
-                                  let value = compare_scalar_values(
-                                      bcx, test_val, val,
-                                      signed_int, ast::BiEq);
-                                  rslt(bcx, value)
-                              }
-                              lower_bound(
-                                  Result {bcx, val: val}) => {
-                                  let value = compare_scalar_values(
-                                      bcx, test_val, val,
-                                      signed_int, ast::BiGe);
-                                  rslt(bcx, value)
-                              }
-                              range_result(
-                                  Result {val: vbegin, ..},
-                                  Result {bcx, val: vend}) => {
-                                  let llge =
-                                      compare_scalar_values(
-                                          bcx, test_val,
-                                          vbegin, signed_int, ast::BiGe);
-                                  let llle =
-                                      compare_scalar_values(
-                                          bcx, test_val, vend,
-                                          signed_int, ast::BiLe);
-                                  rslt(bcx, And(bcx, llge, llle))
-                              }
+                      match trans_opt(bcx, opt) {
+                          single_result(
+                              Result {bcx, val}) => {
+                              let value = compare_scalar_values(
+                                  bcx, test_val, val,
+                                  signed_int, ast::BiEq);
+                              rslt(bcx, value)
                           }
-                      })
+                          lower_bound(
+                              Result {bcx, val: val}) => {
+                              let value = compare_scalar_values(
+                                  bcx, test_val, val,
+                                  signed_int, ast::BiGe);
+                              rslt(bcx, value)
+                          }
+                          range_result(
+                              Result {val: vbegin, ..},
+                              Result {bcx, val: vend}) => {
+                              let llge =
+                                  compare_scalar_values(
+                                  bcx, test_val,
+                                  vbegin, signed_int, ast::BiGe);
+                              let llle =
+                                  compare_scalar_values(
+                                  bcx, test_val, vend,
+                                  signed_int, ast::BiLe);
+                              rslt(bcx, And(bcx, llge, llle))
+                          }
+                      }
                   };
-                  bcx = sub_block(after_cx, "compare_vec_len_next");
+                  bcx = fcx.new_temp_block("compare_vec_len_next");
 
                   // If none of these subcases match, move on to the
                   // next condition.
@@ -1817,9 +1800,7 @@ pub fn trans_match<'a>(
                    dest: Dest)
                    -> &'a Block<'a> {
     let _icx = push_ctxt("match::trans_match");
-    with_scope(bcx, match_expr.info(), "match", |bcx| {
-        trans_match_inner(bcx, discr_expr, arms, dest)
-    })
+    trans_match_inner(bcx, match_expr.id, discr_expr, arms, dest)
 }
 
 fn create_bindings_map(bcx: &Block, pat: @ast::Pat) -> BindingsMap {
@@ -1862,19 +1843,18 @@ fn create_bindings_map(bcx: &Block, pat: @ast::Pat) -> BindingsMap {
     return bindings_map;
 }
 
-fn trans_match_inner<'a>(
-                     scope_cx: &'a Block<'a>,
-                     discr_expr: &ast::Expr,
-                     arms: &[ast::Arm],
-                     dest: Dest)
-                     -> &'a Block<'a> {
+fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
+                         match_id: ast::NodeId,
+                         discr_expr: &ast::Expr,
+                         arms: &[ast::Arm],
+                         dest: Dest) -> &'a Block<'a> {
     let _icx = push_ctxt("match::trans_match_inner");
+    let fcx = scope_cx.fcx;
     let mut bcx = scope_cx;
     let tcx = bcx.tcx();
 
-    let discr_datum = unpack_datum!(bcx, {
-        expr::trans_to_datum(bcx, discr_expr)
-    });
+    let discr_datum = unpack_datum!(bcx, expr::trans_to_lvalue(bcx, discr_expr,
+                                                               "match"));
     if bcx.unreachable.get() {
         return bcx;
     }
@@ -1882,7 +1862,7 @@ fn trans_match_inner<'a>(
     let mut arm_datas = ~[];
     let mut matches = ~[];
     for arm in arms.iter() {
-        let body = scope_block(bcx, arm.body.info(), "case_body");
+        let body = fcx.new_id_block("case_body", arm.body.id);
         let bindings_map = create_bindings_map(bcx, arm.pats[0]);
         let arm_data = ArmData {
             bodycx: body,
@@ -1915,7 +1895,7 @@ fn trans_match_inner<'a>(
             Infallible
         }
     };
-    let lldiscr = discr_datum.to_ref_llval(bcx);
+    let lldiscr = discr_datum.val;
     compile_submatch(bcx, matches, [lldiscr], &chk);
 
     let mut arm_cxs = ~[];
@@ -1931,14 +1911,15 @@ fn trans_match_inner<'a>(
         }
 
         // insert bindings into the lllocals map and add cleanups
-        bcx = insert_lllocals(bcx, arm_data.bindings_map, true);
-
+        let cleanup_scope = fcx.push_custom_cleanup_scope();
+        bcx = insert_lllocals(bcx, arm_data.bindings_map,
+                              cleanup::CustomScope(cleanup_scope));
         bcx = controlflow::trans_block(bcx, arm_data.arm.body, dest);
-        bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx));
+        bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
         arm_cxs.push(bcx);
     }
 
-    bcx = controlflow::join_blocks(scope_cx, arm_cxs);
+    bcx = scope_cx.fcx.join_blocks(match_id, arm_cxs);
     return bcx;
 }
 
@@ -1949,17 +1930,18 @@ enum IrrefutablePatternBindingMode {
     BindArgument
 }
 
-pub fn store_local<'a>(
-                   bcx: &'a Block<'a>,
-                   pat: @ast::Pat,
-                   opt_init_expr: Option<@ast::Expr>)
-                   -> &'a Block<'a> {
+pub fn store_local<'a>(bcx: &'a Block<'a>,
+                       local: &ast::Local)
+                       -> &'a Block<'a> {
     /*!
      * Generates code for a local variable declaration like
      * `let <pat>;` or `let <pat> = <opt_init_expr>`.
      */
     let _icx = push_ctxt("match::store_local");
     let mut bcx = bcx;
+    let tcx = bcx.tcx();
+    let pat = local.pat;
+    let opt_init_expr = local.init;
 
     return match opt_init_expr {
         Some(init_expr) => {
@@ -1975,9 +1957,11 @@ pub fn store_local<'a>(
             // it assumes it is matching against a valid value.
             match simple_identifier(pat) {
                 Some(path) => {
+                    let var_scope = cleanup::var_scope(tcx, local.id);
                     return mk_binding_alloca(
-                        bcx, pat.id, path, BindLocal,
-                        |bcx, datum| expr::trans_into(bcx, init_expr, expr::SaveIn(datum.val)));
+                        bcx, pat.id, path, BindLocal, var_scope, (),
+                        |(), bcx, v, _| expr::trans_into(bcx, init_expr,
+                                                         expr::SaveIn(v)));
                 }
 
                 None => {}
@@ -1985,17 +1969,15 @@ pub fn store_local<'a>(
 
             // General path.
             let init_datum =
-                unpack_datum!(
-                    bcx,
-                    expr::trans_to_datum(bcx, init_expr));
+                unpack_datum!(bcx, expr::trans_to_lvalue(bcx, init_expr, "let"));
             if ty::type_is_bot(expr_ty(bcx, init_expr)) {
                 create_dummy_locals(bcx, pat)
             } else {
                 if bcx.sess().asm_comments() {
                     add_comment(bcx, "creating zeroable ref llval");
                 }
-                let llptr = init_datum.to_ref_llval(bcx);
-                return bind_irrefutable_pat(bcx, pat, llptr, BindLocal);
+                let var_scope = cleanup::var_scope(tcx, local.id);
+                bind_irrefutable_pat(bcx, pat, init_datum.val, BindLocal, var_scope)
             }
         }
         None => {
@@ -2003,22 +1985,27 @@ pub fn store_local<'a>(
         }
     };
 
-    fn create_dummy_locals<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat)
-                           -> &'a Block<'a> {
+    fn create_dummy_locals<'a>(mut bcx: &'a Block<'a>,
+                               pat: @ast::Pat)
+                               -> &'a Block<'a> {
         // create dummy memory for the variables if we have no
         // value to store into them immediately
         let tcx = bcx.tcx();
         pat_bindings(tcx.def_map, pat, |_, p_id, _, path| {
-            bcx = mk_binding_alloca(
-                bcx, p_id, path, BindLocal,
-                |bcx, datum| { datum.cancel_clean(bcx); bcx });
-        });
+                let scope = cleanup::var_scope(tcx, p_id);
+                bcx = mk_binding_alloca(
+                    bcx, p_id, path, BindLocal, scope, (),
+                    |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx });
+            });
         bcx
     }
 }
 
-pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, arg: Datum)
-                 -> &'a Block<'a> {
+pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
+                     pat: @ast::Pat,
+                     arg: Datum<Rvalue>,
+                     arg_scope: cleanup::ScopeId)
+                     -> &'a Block<'a> {
     /*!
      * Generates code for argument patterns like `fn foo(<pat>: T)`.
      * Creates entries in the `llargs` map for each of the bindings
@@ -2031,62 +2018,56 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, arg: Datum)
      *   if the argument type is `T`, then `llval` is a `T*`). In some
      *   cases, this code may zero out the memory `llval` points at.
      */
+
     let _icx = push_ctxt("match::store_arg");
 
-    // We always need to cleanup the argument as we exit the fn scope.
-    // Note that we cannot do it before for fear of a fn like
-    //    fn getaddr(~ref x: ~uint) -> *uint {....}
-    // (From test `run-pass/func-arg-ref-pattern.rs`)
-    arg.add_clean(bcx);
-
-    // Debug information (the llvm.dbg.declare intrinsic to be precise) always expects to get an
-    // alloca, which only is the case on the general path, so lets disable the optimized path when
-    // debug info is enabled.
-    let arg_is_alloca = unsafe { llvm::LLVMIsAAllocaInst(arg.val) != ptr::null() };
-
-    let fast_path = (arg_is_alloca || !bcx.ccx().sess.opts.extra_debuginfo)
-                    && simple_identifier(pat).is_some();
-
-    if fast_path {
-        // Optimized path for `x: T` case. This just adopts
-        // `llval` wholesale as the pointer for `x`, avoiding the
-        // general logic which may copy out of `llval`.
-        let mut llargs = bcx.fcx.llargs.borrow_mut();
-        llargs.get().insert(pat.id, arg);
-    } else {
-        // General path. Copy out the values that are used in the
-        // pattern.
-        let llptr = arg.to_ref_llval(bcx);
-        bcx = bind_irrefutable_pat(bcx, pat, llptr, BindArgument);
-    }
+    match simple_identifier(pat) {
+        Some(path) => {
+            // Generate nicer LLVM for the common case of fn a pattern
+            // like `x: T`
+            mk_binding_alloca(
+                bcx, pat.id, path, BindArgument, arg_scope, arg,
+                |arg, bcx, llval, _| arg.store_to(bcx, llval))
+        }
 
-    return bcx;
+        None => {
+            // General path. Copy out the values that are used in the
+            // pattern.
+            let arg = unpack_datum!(
+                bcx, arg.to_lvalue_datum_in_scope(bcx, "__arg", arg_scope));
+            bind_irrefutable_pat(bcx, pat, arg.val,
+                                 BindArgument, arg_scope)
+        }
+    }
 }
 
-fn mk_binding_alloca<'a>(
-                     bcx: &'a Block<'a>,
-                     p_id: ast::NodeId,
-                     path: &ast::Path,
-                     binding_mode: IrrefutablePatternBindingMode,
-                     populate: |&'a Block<'a>, Datum| -> &'a Block<'a>)
-                     -> &'a Block<'a> {
+fn mk_binding_alloca<'a,A>(bcx: &'a Block<'a>,
+                           p_id: ast::NodeId,
+                           path: &ast::Path,
+                           binding_mode: IrrefutablePatternBindingMode,
+                           cleanup_scope: cleanup::ScopeId,
+                           arg: A,
+                           populate: |A, &'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>)
+                         -> &'a Block<'a> {
     let var_ty = node_id_type(bcx, p_id);
     let ident = ast_util::path_to_ident(path);
+
+    // Allocate memory on stack for the binding.
     let llval = alloc_ty(bcx, var_ty, bcx.ident(ident));
-    let datum = Datum {
-        val: llval,
-        ty: var_ty,
-        mode: ByRef(ZeroMem)
+
+    // Subtle: be sure that we *populate* the memory *before*
+    // we schedule the cleanup.
+    let bcx = populate(arg, bcx, llval, var_ty);
+    bcx.fcx.schedule_drop_mem(cleanup_scope, llval, var_ty);
+
+    // Now that memory is initialized and has cleanup scheduled,
+    // create the datum and insert into the local variable map.
+    let datum = Datum(llval, var_ty, Lvalue);
+    let mut llmap = match binding_mode {
+        BindLocal => bcx.fcx.lllocals.borrow_mut(),
+        BindArgument => bcx.fcx.llargs.borrow_mut()
     };
-    {
-        let mut llmap = match binding_mode {
-            BindLocal => bcx.fcx.lllocals.borrow_mut(),
-            BindArgument => bcx.fcx.llargs.borrow_mut()
-        };
-        llmap.get().insert(p_id, datum);
-    }
-    let bcx = populate(bcx, datum);
-    datum.add_clean(bcx);
+    llmap.get().insert(p_id, datum);
     bcx
 }
 
@@ -2094,7 +2075,8 @@ fn bind_irrefutable_pat<'a>(
                         bcx: &'a Block<'a>,
                         pat: @ast::Pat,
                         val: ValueRef,
-                        binding_mode: IrrefutablePatternBindingMode)
+                        binding_mode: IrrefutablePatternBindingMode,
+                        cleanup_scope: cleanup::ScopeId)
                         -> &'a Block<'a> {
     /*!
      * A simple version of the pattern matching code that only handles
@@ -2108,10 +2090,7 @@ fn bind_irrefutable_pat<'a>(
      * # Arguments
      * - bcx: starting basic block context
      * - pat: the irrefutable pattern being matched.
-     * - val: a pointer to the value being matched. If pat matches a value
-     *   of type T, then this is a T*. If the value is moved from `pat`,
-     *   then `*pat` will be zeroed; otherwise, it's existing cleanup
-     *   applies.
+     * - val: the value being matched -- must be an lvalue (by ref, with cleanup)
      * - binding_mode: is this for an argument or a local variable?
      */
 
@@ -2138,24 +2117,20 @@ fn bind_irrefutable_pat<'a>(
                 // binding will live and place it into the appropriate
                 // map.
                 bcx = mk_binding_alloca(
-                    bcx, pat.id, path, binding_mode,
-                    |bcx, var_datum| {
+                    bcx, pat.id, path, binding_mode, cleanup_scope, (),
+                    |(), bcx, llval, ty| {
                         match pat_binding_mode {
                             ast::BindByValue(_) => {
                                 // By value binding: move the value that `val`
                                 // points at into the binding's stack slot.
-                                let datum = Datum {
-                                    val: val,
-                                    ty: var_datum.ty,
-                                    mode: ByRef(ZeroMem)
-                                };
-                                datum.store_to(bcx, INIT, var_datum.val)
+                                let d = Datum(val, ty, Lvalue);
+                                d.store_to(bcx, llval)
                             }
 
                             ast::BindByRef(_) => {
                                 // By ref binding: the value of the variable
                                 // is the pointer `val` itself.
-                                Store(bcx, val, var_datum.val);
+                                Store(bcx, val, llval);
                                 bcx
                             }
                         }
@@ -2163,7 +2138,8 @@ fn bind_irrefutable_pat<'a>(
             }
 
             for &inner_pat in inner.iter() {
-                bcx = bind_irrefutable_pat(bcx, inner_pat, val, binding_mode);
+                bcx = bind_irrefutable_pat(bcx, inner_pat, val,
+                                           binding_mode, cleanup_scope);
             }
         }
         ast::PatEnum(_, ref sub_pats) => {
@@ -2181,7 +2157,8 @@ fn bind_irrefutable_pat<'a>(
                     for sub_pat in sub_pats.iter() {
                         for (i, argval) in args.vals.iter().enumerate() {
                             bcx = bind_irrefutable_pat(bcx, sub_pat[i],
-                                                       *argval, binding_mode);
+                                                       *argval, binding_mode,
+                                                       cleanup_scope);
                         }
                     }
                 }
@@ -2198,7 +2175,8 @@ fn bind_irrefutable_pat<'a>(
                                 let fldptr = adt::trans_field_ptr(bcx, repr,
                                                                   val, 0, i);
                                 bcx = bind_irrefutable_pat(bcx, *elem,
-                                                           fldptr, binding_mode);
+                                                           fldptr, binding_mode,
+                                                           cleanup_scope);
                             }
                         }
                     }
@@ -2219,7 +2197,8 @@ fn bind_irrefutable_pat<'a>(
                     let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys);
                     let fldptr = adt::trans_field_ptr(bcx, pat_repr, val,
                                                       discr, ix);
-                    bcx = bind_irrefutable_pat(bcx, f.pat, fldptr, binding_mode);
+                    bcx = bind_irrefutable_pat(bcx, f.pat, fldptr,
+                                               binding_mode, cleanup_scope);
                 }
             })
         }
@@ -2227,21 +2206,17 @@ fn bind_irrefutable_pat<'a>(
             let repr = adt::represent_node(bcx, pat.id);
             for (i, elem) in elems.iter().enumerate() {
                 let fldptr = adt::trans_field_ptr(bcx, repr, val, 0, i);
-                bcx = bind_irrefutable_pat(bcx, *elem, fldptr, binding_mode);
+                bcx = bind_irrefutable_pat(bcx, *elem, fldptr,
+                                           binding_mode, cleanup_scope);
             }
         }
         ast::PatUniq(inner) => {
-            let pat_ty = node_id_type(bcx, pat.id);
             let llbox = Load(bcx, val);
-            let unboxed = match ty::get(pat_ty).sty {
-                ty::ty_uniq(..) if !ty::type_contents(bcx.tcx(), pat_ty).owns_managed() => llbox,
-                    _ => GEPi(bcx, llbox, [0u, abi::box_field_body])
-            };
-            bcx = bind_irrefutable_pat(bcx, inner, unboxed, binding_mode);
+            bcx = bind_irrefutable_pat(bcx, inner, llbox, binding_mode, cleanup_scope);
         }
         ast::PatRegion(inner) => {
             let loaded_val = Load(bcx, val);
-            bcx = bind_irrefutable_pat(bcx, inner, loaded_val, binding_mode);
+            bcx = bind_irrefutable_pat(bcx, inner, loaded_val, binding_mode, cleanup_scope);
         }
         ast::PatVec(..) => {
             bcx.tcx().sess.span_bug(
@@ -2253,14 +2228,4 @@ fn bind_irrefutable_pat<'a>(
     return bcx;
 }
 
-fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Path> {
-    match pat.node {
-        ast::PatIdent(ast::BindByValue(_), ref path, None) => {
-            Some(path)
-        }
-        _ => {
-            None
-        }
-    }
-}
 
index 25a69174bb2c5e3d94aebab71e038d266e949a7d..91dcae2d1d3084659e8e7fdd2a627366a23e187f 100644 (file)
@@ -628,6 +628,25 @@ pub fn num_args(r: &Repr, discr: Disr) -> uint {
     }
 }
 
+/// Access a field, at a point when the value's case is known.
+pub fn deref_ty(ccx: &CrateContext, r: &Repr) -> ty::t {
+    match *r {
+        CEnum(..) => {
+            ccx.sess.bug("deref of c-like enum")
+        }
+        Univariant(ref st, _) => {
+            st.fields[0]
+        }
+        General(_, ref cases) => {
+            assert!(cases.len() == 1);
+            cases[0].fields[0]
+        }
+        NullablePointer{ .. } => {
+            ccx.sess.bug("deref of nullable ptr")
+        }
+    }
+}
+
 /// Access a field, at a point when the value's case is known.
 pub fn trans_field_ptr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr,
                        ix: uint) -> ValueRef {
index 11f217f3cb4b1ae3885c73fc420273d3dbdaf011..bae35f68ada5630dd3e51edb4db1b6b358232356 100644 (file)
 use middle::trans::build::*;
 use middle::trans::callee;
 use middle::trans::common::*;
-use middle::trans::expr::*;
-use middle::trans::type_of::*;
+use middle::trans::cleanup;
+use middle::trans::cleanup::CleanupMethods;
+use middle::trans::expr;
+use middle::trans::type_of;
 
 use middle::trans::type_::Type;
 
 // Take an inline assembly expression and splat it out via LLVM
 pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm)
                         -> &'a Block<'a> {
+    let fcx = bcx.fcx;
     let mut bcx = bcx;
     let mut constraints = ~[];
-    let mut cleanups = ~[];
     let mut output_types = ~[];
 
+    let temp_scope = fcx.push_custom_cleanup_scope();
+
     // Prepare the output operands
     let outputs = ia.outputs.map(|&(c, out)| {
         constraints.push(c);
 
-        let out_datum = unpack_datum!(bcx, trans_to_datum(bcx, out));
-        output_types.push(type_of(bcx.ccx(), out_datum.ty));
+        let out_datum = unpack_datum!(bcx, expr::trans(bcx, out));
+        output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
         out_datum.val
 
     });
 
-    for c in cleanups.iter() {
-        revoke_clean(bcx, *c);
-    }
-    cleanups.clear();
-
     // Now the input operands
     let inputs = ia.inputs.map(|&(c, input)| {
         constraints.push(c);
@@ -56,14 +55,13 @@ pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm)
             callee::trans_arg_expr(bcx,
                                    expr_ty(bcx, input),
                                    input,
-                                   &mut cleanups,
+                                   cleanup::CustomScope(temp_scope),
                                    callee::DontAutorefArg)
         })
     });
 
-    for c in cleanups.iter() {
-        revoke_clean(bcx, *c);
-    }
+    // no failure occurred preparing operands, no need to cleanup
+    fcx.pop_custom_cleanup_scope(temp_scope);
 
     let mut constraints = constraints.connect(",");
 
index 6fa3764fb379bbe1431212d91ef15c84adaa3cb9..ef40629946df0dadf42c63daaea45aa91fcb4a52 100644 (file)
 use middle::astencode;
 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
 use middle::lang_items::{MallocFnLangItem, ClosureExchangeMallocFnLangItem};
-use middle::lang_items::{EhPersonalityLangItem};
 use middle::trans::_match;
 use middle::trans::adt;
-use middle::trans::base;
 use middle::trans::build::*;
 use middle::trans::builder::{Builder, noname};
 use middle::trans::callee;
+use middle::trans::cleanup;
+use middle::trans::cleanup::CleanupMethods;
 use middle::trans::common::*;
 use middle::trans::consts;
 use middle::trans::controlflow;
 use middle::trans::datum;
+// use middle::trans::datum::{Datum, Lvalue, Rvalue, ByRef, ByValue};
 use middle::trans::debuginfo;
 use middle::trans::expr;
 use middle::trans::foreign;
 use std::libc::c_uint;
 use std::vec;
 use std::local_data;
-use syntax::ast::Name;
 use syntax::ast_map::{PathName, PathPrettyName, path_elem_to_str};
 use syntax::ast_util::{local_def, is_local};
 use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token;
-use syntax::parse::token::{special_idents};
-use syntax::print::pprust::stmt_to_str;
-use syntax::{ast, ast_util, codemap, ast_map};
+use syntax::{ast, ast_util, ast_map};
 use syntax::attr::AttrMetaMethods;
 use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic, OsWin32};
 use syntax::visit;
@@ -177,32 +175,57 @@ fn drop(&mut self) {
 }
 
 // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
-pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
+fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
+           ty: Type, output: ty::t) -> ValueRef {
     let llfn: ValueRef = name.with_c_str(|buf| {
         unsafe {
             llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
         }
     });
 
+    match ty::get(output).sty {
+        // functions returning bottom may unwind, but can never return normally
+        ty::ty_bot => {
+            unsafe {
+                llvm::LLVMAddFunctionAttr(llfn, lib::llvm::NoReturnAttribute as c_uint)
+            }
+        }
+        // `~` pointer return values never alias because ownership is transferred
+        // FIXME #6750 ~Trait cannot be directly marked as
+        // noalias because the actual object pointer is nested.
+        ty::ty_uniq(..) | // ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
+        ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
+            unsafe {
+                llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
+            }
+        }
+        _ => {}
+    }
+
     lib::llvm::SetFunctionCallConv(llfn, cc);
     // Function addresses in Rust are never significant, allowing functions to be merged.
     lib::llvm::SetUnnamedAddr(llfn, true);
-    return llfn;
+
+    llfn
 }
 
 // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
-pub fn decl_cdecl_fn(llmod: ModuleRef, name: &str, ty: Type) -> ValueRef {
-    return decl_fn(llmod, name, lib::llvm::CCallConv, ty);
+pub fn decl_cdecl_fn(llmod: ModuleRef,
+                     name: &str,
+                     ty: Type,
+                     output: ty::t) -> ValueRef {
+    decl_fn(llmod, name, lib::llvm::CCallConv, ty, output)
 }
 
 // only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
-pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
-                     cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
+pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef,
+                     name: &str, cc: lib::llvm::CallConv,
+                     ty: Type, output: ty::t) -> ValueRef {
     match externs.find_equiv(&name) {
         Some(n) => return *n,
-        None => ()
+        None => {}
     }
-    let f = decl_fn(llmod, name, cc, ty);
+    let f = decl_fn(llmod, name, cc, ty, output);
     externs.insert(name.to_owned(), f);
     f
 }
@@ -233,24 +256,7 @@ fn decl_rust_fn(ccx: &CrateContext,
                 output: ty::t,
                 name: &str) -> ValueRef {
     let llfty = type_of_rust_fn(ccx, self_ty, inputs, output);
-    let llfn = decl_cdecl_fn(ccx.llmod, name, llfty);
-
-    match ty::get(output).sty {
-        // functions returning bottom may unwind, but can never return normally
-        ty::ty_bot => {
-            unsafe {
-                llvm::LLVMAddFunctionAttr(llfn, lib::llvm::NoReturnAttribute as c_uint)
-            }
-        }
-        // `~` pointer return values never alias because ownership is transferred
-        ty::ty_uniq(..) |
-        ty::ty_vec(_, ty::vstore_uniq) => {
-            unsafe {
-                llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
-            }
-        }
-        _ => ()
-    }
+    let llfn = decl_cdecl_fn(ccx.llmod, name, llfty, output);
 
     let uses_outptr = type_of::return_uses_outptr(ccx, output);
     let offset = if uses_outptr { 2 } else { 1 };
@@ -259,8 +265,10 @@ fn decl_rust_fn(ccx: &CrateContext,
         let llarg = unsafe { llvm::LLVMGetParam(llfn, (offset + i) as c_uint) };
         match ty::get(arg_ty).sty {
             // `~` pointer parameters never alias because ownership is transferred
-            ty::ty_uniq(..) |
-            ty::ty_vec(_, ty::vstore_uniq) |
+            // FIXME #6750 ~Trait cannot be directly marked as
+            // noalias because the actual object pointer is nested.
+            ty::ty_uniq(..) | // ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
+            ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) |
             ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, ..}) => {
                 unsafe {
                     llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
@@ -357,20 +365,18 @@ fn require_alloc_fn(bcx: &Block, t: ty::t, it: LangItem) -> ast::DefId {
         rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to()))
     } else {
         // we treat ~fn, @fn and @[] as @ here, which isn't ideal
-        let (mk_fn, langcall) = match heap {
-            heap_managed | heap_managed_unique => {
-                (ty::mk_imm_box,
-                 require_alloc_fn(bcx, t, MallocFnLangItem))
+        let langcall = match heap {
+            heap_managed => {
+                require_alloc_fn(bcx, t, MallocFnLangItem)
             }
             heap_exchange_closure => {
-                (ty::mk_imm_box,
-                 require_alloc_fn(bcx, t, ClosureExchangeMallocFnLangItem))
+                require_alloc_fn(bcx, t, ClosureExchangeMallocFnLangItem)
             }
             _ => fail!("heap_exchange already handled")
         };
 
         // Grab the TypeRef type of box_ptr_ty.
-        let box_ptr_ty = mk_fn(bcx.tcx(), t);
+        let box_ptr_ty = ty::mk_box(bcx.tcx(), t);
         let llty = type_of(ccx, box_ptr_ty);
 
         // Get the tydesc for the body:
@@ -384,9 +390,7 @@ fn require_alloc_fn(bcx: &Block, t: ty::t, it: LangItem) -> ast::DefId {
             langcall,
             [tydesc, size],
             None);
-        let r = rslt(r.bcx, PointerCast(r.bcx, r.val, llty));
-        maybe_set_managed_unique_rc(r.bcx, r.val, heap);
-        r
+        rslt(r.bcx, PointerCast(r.bcx, r.val, llty))
     }
 }
 
@@ -433,27 +437,6 @@ pub fn malloc_general<'a>(bcx: &'a Block, t: ty::t, heap: heap)
     malloc_general_dyn(bcx, t, heap, llsize_of(bcx.ccx(), ty))
 }
 
-pub fn heap_for_unique(bcx: &Block, t: ty::t) -> heap {
-    if ty::type_contents(bcx.tcx(), t).owns_managed() {
-        heap_managed_unique
-    } else {
-        heap_exchange
-    }
-}
-
-pub fn maybe_set_managed_unique_rc(bcx: &Block, bx: ValueRef, heap: heap) {
-    assert!(heap != heap_exchange);
-    if heap == heap_managed_unique {
-        // In cases where we are looking at a unique-typed allocation in the
-        // managed heap (thus have refcount 1 from the managed allocator),
-        // such as a ~(@foo) or such. These need to have their refcount forced
-        // to -2 so the annihilator ignores them.
-        let rc = GEPi(bcx, bx, [0u, abi::box_field_refcnt]);
-        let rc_val = C_int(bcx.ccx(), -2);
-        Store(bcx, rc_val, rc);
-    }
-}
-
 // Type descriptor and type glue stuff
 
 pub fn get_tydesc_simple(ccx: &CrateContext, t: ty::t) -> ValueRef {
@@ -584,11 +567,8 @@ pub fn get_res_dtor(ccx: @CrateContext,
 
         {
             let mut externs = ccx.externs.borrow_mut();
-            get_extern_fn(externs.get(),
-                          ccx.llmod,
-                          name,
-                          lib::llvm::CCallConv,
-                          llty)
+            get_extern_fn(externs.get(), ccx.llmod, name,
+                          lib::llvm::CCallConv, llty, ty::mk_nil())
         }
     }
 }
@@ -775,7 +755,8 @@ fn iter_variant<'r,
           }
       }
       ty::ty_enum(tid, ref substs) => {
-          let ccx = cx.ccx();
+          let fcx = cx.fcx;
+          let ccx = fcx.ccx;
 
           let repr = adt::represent_type(ccx, t);
           let variants = ty::enum_variants(ccx.tcx, tid);
@@ -791,16 +772,16 @@ fn iter_variant<'r,
               }
               (_match::switch, Some(lldiscrim_a)) => {
                   cx = f(cx, lldiscrim_a, ty::mk_int());
-                  let unr_cx = sub_block(cx, "enum-iter-unr");
+                  let unr_cx = fcx.new_temp_block("enum-iter-unr");
                   Unreachable(unr_cx);
                   let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,
                                         n_variants);
-                  let next_cx = sub_block(cx, "enum-iter-next");
+                  let next_cx = fcx.new_temp_block("enum-iter-next");
 
                   for variant in (*variants).iter() {
                       let variant_cx =
-                          sub_block(cx, ~"enum-iter-variant-" +
-                                    variant.disr_val.to_str());
+                          fcx.new_temp_block(~"enum-iter-variant-" +
+                                             variant.disr_val.to_str());
                       let variant_cx =
                           iter_variant(variant_cx, repr, av, *variant,
                                        substs.tps, |x,y,z| f(x,y,z));
@@ -919,7 +900,8 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
                     let cconv = c.unwrap_or(lib::llvm::CCallConv);
                     let llty = type_of_fn_from_ty(ccx, None, t);
                     let mut externs = ccx.externs.borrow_mut();
-                    get_extern_fn(externs.get(), ccx.llmod, name, cconv, llty)
+                    get_extern_fn(externs.get(), ccx.llmod, name,
+                                  cconv, llty, fn_ty.sig.output)
                 }
             }
         }
@@ -946,23 +928,27 @@ pub fn invoke<'a>(
         return (C_null(Type::i8()), bcx);
     }
 
-    match bcx.node_info {
-        None => debug!("invoke at ???"),
-        Some(node_info) => {
+    match bcx.opt_node_id {
+        None => {
+            debug!("invoke at ???");
+        }
+        Some(id) => {
             debug!("invoke at {}",
-                   bcx.sess().codemap.span_to_str(node_info.span));
+                   ast_map::node_id_to_str(bcx.tcx().items,
+                                           id,
+                                           token::get_ident_interner()));
         }
     }
 
-    if need_invoke(bcx) {
+    if bcx.fcx.needs_invoke() {
         unsafe {
             debug!("invoking {} at {}", llfn, bcx.llbb);
             for &llarg in llargs.iter() {
                 debug!("arg: {}", llarg);
             }
         }
-        let normal_bcx = sub_block(bcx, "normal return");
-        let landing_pad = get_landing_pad(bcx);
+        let normal_bcx = bcx.fcx.new_temp_block("normal-return");
+        let landing_pad = bcx.fcx.get_landing_pad();
 
         match call_info {
             Some(info) => debuginfo::set_source_location(bcx.fcx, info.id, info.span),
@@ -1004,146 +990,9 @@ pub fn need_invoke(bcx: &Block) -> bool {
         return false;
     }
 
-    if have_cached_lpad(bcx) {
-        return true;
-    }
-
-    // Walk the scopes to look for cleanups
-    let mut cur = bcx;
-    let mut cur_scope = cur.scope.get();
-    loop {
-        cur_scope = match cur_scope {
-            Some(inf) => {
-                let cleanups = inf.cleanups.borrow();
-                for cleanup in cleanups.get().iter() {
-                    match *cleanup {
-                        Clean(_, cleanup_type) | CleanTemp(_, _, cleanup_type) => {
-                            if cleanup_type == normal_exit_and_unwind {
-                                return true;
-                            }
-                        }
-                    }
-                }
-                inf.parent
-            }
-            None => {
-                cur = match cur.parent {
-                    Some(next) => next,
-                    None => return false
-                };
-                cur.scope.get()
-            }
-        }
-    }
-}
-
-pub fn have_cached_lpad(bcx: &Block) -> bool {
-    let mut res = false;
-    in_lpad_scope_cx(bcx, |inf| {
-        match inf.landing_pad.get() {
-          Some(_) => res = true,
-          None => res = false
-        }
-    });
-    return res;
-}
-
-pub fn in_lpad_scope_cx<'a>(bcx: &'a Block<'a>, f: |si: &'a ScopeInfo<'a>|) {
-    let mut bcx = bcx;
-    let mut cur_scope = bcx.scope.get();
-    loop {
-        cur_scope = match cur_scope {
-            Some(inf) => {
-                if !inf.empty_cleanups() || (inf.parent.is_none() && bcx.parent.is_none()) {
-                    f(inf);
-                    return;
-                }
-                inf.parent
-            }
-            None => {
-                bcx = block_parent(bcx);
-                bcx.scope.get()
-            }
-        }
-    }
-}
-
-pub fn get_landing_pad<'a>(bcx: &'a Block<'a>) -> BasicBlockRef {
-    let _icx = push_ctxt("get_landing_pad");
-
-    let mut cached = None;
-    let mut pad_bcx = bcx; // Guaranteed to be set below
-    in_lpad_scope_cx(bcx, |inf| {
-        // If there is a valid landing pad still around, use it
-        match inf.landing_pad.get() {
-          Some(target) => cached = Some(target),
-          None => {
-            pad_bcx = lpad_block(bcx, "unwind");
-            inf.landing_pad.set(Some(pad_bcx.llbb));
-          }
-        }
-    });
-    // Can't return from block above
-    match cached { Some(b) => return b, None => () }
-    // 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_([Type::i8p(), Type::i32()], false);
-    // The exception handling personality function.
-    let personality = callee::trans_fn_ref(bcx,
-                                           langcall(bcx, None, "", EhPersonalityLangItem),
-                                           0).llfn;
-    // The only landing pad clause will be 'cleanup'
-    let llretval = LandingPad(pad_bcx, llretty, personality, 1u);
-    // The landing pad block is a cleanup
-    SetCleanup(pad_bcx, llretval);
-
-    // We store the retval in a function-central alloca, so that calls to
-    // Resume can find it.
-    match bcx.fcx.personality.get() {
-      Some(addr) => Store(pad_bcx, llretval, addr),
-      None => {
-        let addr = alloca(pad_bcx, val_ty(llretval), "");
-        bcx.fcx.personality.set(Some(addr));
-        Store(pad_bcx, llretval, addr);
-      }
-    }
-
-    // Unwind all parent scopes, and finish with a Resume instr
-    cleanup_and_leave(pad_bcx, None, None);
-    return pad_bcx.llbb;
+    bcx.fcx.needs_invoke()
 }
 
-pub fn find_bcx_for_scope<'a>(bcx: &'a Block<'a>, scope_id: ast::NodeId)
-                          -> &'a Block<'a> {
-    let mut bcx_sid = bcx;
-    let mut cur_scope = bcx_sid.scope.get();
-    loop {
-        cur_scope = match cur_scope {
-            Some(inf) => {
-                match inf.node_info {
-                    Some(NodeInfo { id, .. }) if id == scope_id => {
-                        return bcx_sid
-                    }
-                    // FIXME(#6268, #6248) hacky cleanup for nested method calls
-                    Some(NodeInfo { callee_id: Some(id), .. }) if id == scope_id => {
-                        return bcx_sid
-                    }
-                    _ => inf.parent
-                }
-            }
-            None => {
-                bcx_sid = match bcx_sid.parent {
-                    None => bcx.tcx().sess.bug(format!("no enclosing scope with id {}", scope_id)),
-                    Some(bcx_par) => bcx_par
-                };
-                bcx_sid.scope.get()
-            }
-        }
-    }
-}
-
-
 pub fn do_spill(bcx: &Block, v: ValueRef, t: ty::t) -> ValueRef {
     if ty::type_is_bot(t) {
         return C_null(Type::i8p());
@@ -1198,139 +1047,7 @@ pub fn init_local<'a>(bcx: &'a Block<'a>, local: &ast::Local)
         }
     }
 
-    _match::store_local(bcx, local.pat, local.init)
-}
-
-pub fn trans_stmt<'a>(cx: &'a Block<'a>, s: &ast::Stmt) -> &'a Block<'a> {
-    let _icx = push_ctxt("trans_stmt");
-    debug!("trans_stmt({})", stmt_to_str(s, cx.tcx().sess.intr()));
-
-    if cx.sess().asm_comments() {
-        add_span_comment(cx, s.span, stmt_to_str(s, cx.ccx().sess.intr()));
-    }
-
-    let mut bcx = cx;
-
-    match s.node {
-        ast::StmtExpr(e, _) | ast::StmtSemi(e, _) => {
-            bcx = expr::trans_into(cx, e, expr::Ignore);
-        }
-        ast::StmtDecl(d, _) => {
-            match d.node {
-                ast::DeclLocal(ref local) => {
-                    bcx = init_local(bcx, *local);
-                    if cx.sess().opts.extra_debuginfo {
-                        debuginfo::create_local_var_metadata(bcx, *local);
-                    }
-                }
-                ast::DeclItem(i) => trans_item(cx.fcx.ccx, i)
-            }
-        }
-        ast::StmtMac(..) => cx.tcx().sess.bug("unexpanded macro")
-    }
-
-    return bcx;
-}
-
-// You probably don't want to use this one. See the
-// next three functions instead.
-pub fn new_block<'a>(
-                 cx: &'a FunctionContext<'a>,
-                 parent: Option<&'a Block<'a>>,
-                 scope: Option<&'a ScopeInfo<'a>>,
-                 is_lpad: bool,
-                 name: &str,
-                 opt_node_info: Option<NodeInfo>)
-                 -> &'a Block<'a> {
-    unsafe {
-        let llbb = name.with_c_str(|buf| {
-            llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf)
-        });
-        let bcx = Block::new(llbb, parent, is_lpad, opt_node_info, cx);
-        bcx.scope.set(scope);
-        for cx in parent.iter() {
-            if cx.unreachable.get() {
-                Unreachable(bcx);
-                break;
-            }
-        }
-        bcx
-    }
-}
-
-pub fn simple_block_scope<'a>(
-                          fcx: &'a FunctionContext<'a>,
-                          parent: Option<&'a ScopeInfo<'a>>,
-                          node_info: Option<NodeInfo>)
-                          -> &'a ScopeInfo<'a> {
-    fcx.scope_info_arena.alloc(ScopeInfo {
-        parent: parent,
-        loop_break: None,
-        loop_label: None,
-        cleanups: RefCell::new(~[]),
-        cleanup_paths: RefCell::new(~[]),
-        landing_pad: Cell::new(None),
-        node_info: node_info,
-    })
-}
-
-// Use this when you're at the top block of a function or the like.
-pub fn top_scope_block<'a>(
-                       fcx: &'a FunctionContext<'a>,
-                       opt_node_info: Option<NodeInfo>)
-                       -> &'a Block<'a> {
-    new_block(fcx,
-              None,
-              Some(simple_block_scope(fcx, None, opt_node_info)),
-              false,
-              "function top level",
-              opt_node_info)
-}
-
-pub fn scope_block<'a>(
-                   bcx: &'a Block<'a>,
-                   opt_node_info: Option<NodeInfo>,
-                   n: &str)
-                   -> &'a Block<'a> {
-    new_block(bcx.fcx,
-              Some(bcx),
-              Some(simple_block_scope(bcx.fcx, None, opt_node_info)),
-              bcx.is_lpad,
-              n,
-              opt_node_info)
-}
-
-pub fn loop_scope_block<'a>(
-                        bcx: &'a Block<'a>,
-                        loop_break: &'a Block<'a>,
-                        loop_label: Option<Name>,
-                        n: &str,
-                        opt_node_info: Option<NodeInfo>)
-                        -> &'a Block<'a> {
-    new_block(bcx.fcx,
-              Some(bcx),
-              Some(bcx.fcx.scope_info_arena.alloc(ScopeInfo {
-                parent: None,
-                loop_break: Some(loop_break),
-                loop_label: loop_label,
-                cleanups: RefCell::new(~[]),
-                cleanup_paths: RefCell::new(~[]),
-                landing_pad: Cell::new(None),
-                node_info: opt_node_info,
-              })),
-              bcx.is_lpad,
-              n,
-              opt_node_info)
-}
-
-// Use this when creating a block for the inside of a landing pad.
-pub fn lpad_block<'a>(bcx: &'a Block<'a>, n: &str) -> &'a Block<'a> {
-    new_block(bcx.fcx, Some(bcx), None, true, n, None)
-}
-
-// Use this when you're making a general CFG BB within a scope.
-pub fn sub_block<'a>(bcx: &'a Block<'a>, n: &str) -> &'a Block<'a> {
-    new_block(bcx.fcx, Some(bcx), None, bcx.is_lpad, n, None)
+    _match::store_local(bcx, local)
 }
 
 pub fn raw_block<'a>(
@@ -1338,236 +1055,7 @@ pub fn raw_block<'a>(
                  is_lpad: bool,
                  llbb: BasicBlockRef)
                  -> &'a Block<'a> {
-    Block::new(llbb, None, is_lpad, None, fcx)
-}
-
-
-// trans_block_cleanups: Go through all the cleanups attached to this
-// block and execute them.
-//
-// When translating a block that introduces new variables during its scope, we
-// need to make sure those variables go out of scope when the block ends.  We
-// do that by running a 'cleanup' function for each variable.
-// trans_block_cleanups runs all the cleanup functions for the block.
-pub fn trans_block_cleanups<'a>(bcx: &'a Block<'a>, cleanups: ~[cleanup])
-                            -> &'a Block<'a> {
-    trans_block_cleanups_(bcx, cleanups, false)
-}
-
-pub fn trans_block_cleanups_<'a>(
-                             bcx: &'a Block<'a>,
-                             cleanups: &[cleanup],
-                             is_lpad: bool)
-                             -> &'a Block<'a> {
-    let _icx = push_ctxt("trans_block_cleanups");
-    // NB: Don't short-circuit even if this block is unreachable because
-    // GC-based cleanup needs to the see that the roots are live.
-    let no_lpads = bcx.ccx().sess.no_landing_pads();
-    if bcx.unreachable.get() && !no_lpads {
-        return bcx
-    }
-    let mut bcx = bcx;
-    for cu in cleanups.rev_iter() {
-        match *cu {
-            Clean(cfn, cleanup_type) | CleanTemp(_, cfn, cleanup_type) => {
-                // Some types don't need to be cleaned up during
-                // landing pads because they can be freed en mass later
-                if cleanup_type == normal_exit_and_unwind || !is_lpad {
-                    bcx = cfn.clean(bcx);
-                }
-            }
-        }
-    }
-    return bcx;
-}
-
-// In the last argument, Some(block) mean jump to this block, and none means
-// this is a landing pad and leaving should be accomplished with a resume
-// instruction.
-pub fn cleanup_and_leave<'a>(
-                         bcx: &'a Block<'a>,
-                         upto: Option<BasicBlockRef>,
-                         leave: Option<BasicBlockRef>) {
-    let _icx = push_ctxt("cleanup_and_leave");
-    let mut cur = bcx;
-    let mut bcx = bcx;
-    let is_lpad = leave == None;
-    loop {
-        debug!("cleanup_and_leave: leaving {}", cur.to_str());
-
-        let mut cur_scope = cur.scope.get();
-        loop {
-            cur_scope = match cur_scope {
-                Some (inf) if !inf.empty_cleanups() => {
-                    let (sub_cx, dest, inf_cleanups) = {
-                        let inf = &*inf;
-                        let mut skip = 0;
-                        let mut dest = None;
-                        {
-                            let cleanup_paths = inf.cleanup_paths.borrow();
-                            let r = cleanup_paths.get()
-                                                 .rev_iter()
-                                                 .find(|cp| {
-                                cp.target == leave
-                            });
-                            for cp in r.iter() {
-                                let cleanups = inf.cleanups.borrow();
-                                if cp.size == cleanups.get().len() {
-                                    Br(bcx, cp.dest);
-                                    return;
-                                }
-
-                                skip = cp.size;
-                                dest = Some(cp.dest);
-                            }
-                        }
-                        let sub_cx = sub_block(bcx, "cleanup");
-                        Br(bcx, sub_cx.llbb);
-                        let cleanups = inf.cleanups.borrow();
-                        let mut cleanup_paths = inf.cleanup_paths
-                                                   .borrow_mut();
-                        cleanup_paths.get().push(cleanup_path {
-                            target: leave,
-                            size: cleanups.get().len(),
-                            dest: sub_cx.llbb
-                        });
-                        (sub_cx, dest, cleanups.get().tailn(skip).to_owned())
-                    };
-                    bcx = trans_block_cleanups_(sub_cx,
-                                                inf_cleanups,
-                                                is_lpad);
-                    for &dest in dest.iter() {
-                        Br(bcx, dest);
-                        return;
-                    }
-                    inf.parent
-                }
-                Some(inf) => inf.parent,
-                None => break
-            }
-        }
-
-        match upto {
-          Some(bb) => { if cur.llbb == bb { break; } }
-          _ => ()
-        }
-        cur = match cur.parent {
-          Some(next) => next,
-          None => { assert!(upto.is_none()); break; }
-        };
-    }
-    match leave {
-      Some(target) => Br(bcx, target),
-      None => {
-          let ll_load = Load(bcx, bcx.fcx.personality.get().unwrap());
-          Resume(bcx, ll_load);
-      }
-    }
-}
-
-pub fn cleanup_block<'a>(bcx: &'a Block<'a>, upto: Option<BasicBlockRef>)
-                     -> &'a Block<'a> {
-    let _icx = push_ctxt("cleanup_block");
-    let mut cur = bcx;
-    let mut bcx = bcx;
-    loop {
-        debug!("cleanup_block: {}", cur.to_str());
-
-        let mut cur_scope = cur.scope.get();
-        loop {
-            cur_scope = match cur_scope {
-                Some(inf) => {
-                    let cleanups = inf.cleanups.borrow();
-                    bcx = trans_block_cleanups_(bcx,
-                                                cleanups.get().to_owned(),
-                                                false);
-                    inf.parent
-                }
-                None => break
-            }
-        }
-
-        match upto {
-          Some(bb) => { if cur.llbb == bb { break; } }
-          _ => ()
-        }
-        cur = match cur.parent {
-          Some(next) => next,
-          None => { assert!(upto.is_none()); break; }
-        };
-    }
-    bcx
-}
-
-pub fn cleanup_and_Br<'a>(
-                      bcx: &'a Block<'a>,
-                      upto: &'a Block<'a>,
-                      target: BasicBlockRef) {
-    let _icx = push_ctxt("cleanup_and_Br");
-    cleanup_and_leave(bcx, Some(upto.llbb), Some(target));
-}
-
-pub fn leave_block<'a>(bcx: &'a Block<'a>, out_of: &'a Block<'a>)
-                   -> &'a Block<'a> {
-    let _icx = push_ctxt("leave_block");
-    let next_cx = sub_block(block_parent(out_of), "next");
-    if bcx.unreachable.get() {
-        Unreachable(next_cx);
-    }
-    cleanup_and_Br(bcx, out_of, next_cx.llbb);
-    next_cx
-}
-
-pub fn with_scope<'a>(
-                  bcx: &'a Block<'a>,
-                  opt_node_info: Option<NodeInfo>,
-                  name: &str,
-                  f: |&'a Block<'a>| -> &'a Block<'a>)
-                  -> &'a Block<'a> {
-    let _icx = push_ctxt("with_scope");
-
-    debug!("with_scope(bcx={}, opt_node_info={:?}, name={})",
-           bcx.to_str(), opt_node_info, name);
-    let _indenter = indenter();
-
-    let scope = simple_block_scope(bcx.fcx, bcx.scope.get(), opt_node_info);
-    bcx.scope.set(Some(scope));
-    let ret = f(bcx);
-    let ret = trans_block_cleanups_(ret, scope.cleanups.get(), false);
-    bcx.scope.set(scope.parent);
-    ret
-}
-
-pub fn with_scope_result<'a>(
-                         bcx: &'a Block<'a>,
-                         opt_node_info: Option<NodeInfo>,
-                         _name: &str,
-                         f: |&'a Block<'a>| -> Result<'a>)
-                         -> Result<'a> {
-    let _icx = push_ctxt("with_scope_result");
-
-    let scope = simple_block_scope(bcx.fcx, bcx.scope.get(), opt_node_info);
-    bcx.scope.set(Some(scope));
-    let Result { bcx: out_bcx, val } = f(bcx);
-    let out_bcx = trans_block_cleanups_(out_bcx, scope.cleanups.get(), false);
-    bcx.scope.set(scope.parent);
-
-    rslt(out_bcx, val)
-}
-
-pub fn with_scope_datumblock<'a>(
-                             bcx: &'a Block<'a>,
-                             opt_node_info: Option<NodeInfo>,
-                             name: &str,
-                             f: |&'a Block| -> datum::DatumBlock<'a>)
-                             -> datum::DatumBlock<'a> {
-    use middle::trans::datum::DatumBlock;
-
-    let _icx = push_ctxt("with_scope_result");
-    let scope_cx = scope_block(bcx, opt_node_info, name);
-    Br(bcx, scope_cx.llbb);
-    let DatumBlock {bcx, datum} = f(scope_cx);
-    DatumBlock {bcx: leave_block(bcx, scope_cx), datum: datum}
+    Block::new(llbb, is_lpad, None, fcx)
 }
 
 pub fn block_locals(b: &ast::Block, it: |@ast::Local|) {
@@ -1590,8 +1078,9 @@ pub fn with_cond<'a>(
                  f: |&'a Block<'a>| -> &'a Block<'a>)
                  -> &'a Block<'a> {
     let _icx = push_ctxt("with_cond");
-    let next_cx = base::sub_block(bcx, "next");
-    let cond_cx = base::sub_block(bcx, "cond");
+    let fcx = bcx.fcx;
+    let next_cx = fcx.new_temp_block("next");
+    let cond_cx = fcx.new_temp_block("cond");
     CondBr(bcx, val, cond_cx.llbb, next_cx.llbb);
     let after_cx = f(cond_cx);
     if !after_cx.terminated.get() {
@@ -1742,24 +1231,25 @@ pub fn make_return_pointer(fcx: &FunctionContext, output_type: ty::t)
 // NB: must keep 4 fns in sync:
 //
 //  - type_of_fn
-//  - create_llargs_for_fn_args.
+//  - create_datums_for_fn_args.
 //  - new_fn_ctxt
 //  - trans_args
 //
 // Be warned! You must call `init_function` before doing anything with the
 // returned function context.
-pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
-                        path: ast_map::Path,
-                        llfndecl: ValueRef,
-                        id: ast::NodeId,
-                        output_type: ty::t,
-                        param_substs: Option<@param_substs>,
-                        sp: Option<Span>)
-                        -> FunctionContext {
+pub fn new_fn_ctxt_detailed(ccx: @CrateContext,
+                            path: ast_map::Path,
+                            llfndecl: ValueRef,
+                            id: ast::NodeId,
+                            output_type: ty::t,
+                            param_substs: Option<@param_substs>,
+                            sp: Option<Span>)
+                            -> FunctionContext {
     for p in param_substs.iter() { p.validate(); }
 
-    debug!("new_fn_ctxt_w_id(path={}, id={:?}, \
-            param_substs={})",
+    debug!("new_fn_ctxt_detailed(path={},
+           id={:?}, \
+           param_substs={})",
            path_str(ccx.sess, path),
            id,
            param_substs.repr(ccx.tcx));
@@ -1793,9 +1283,9 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
           span: sp,
           path: path,
           block_arena: TypedArena::new(),
-          scope_info_arena: TypedArena::new(),
           ccx: ccx,
           debug_context: debug_context,
+          scopes: RefCell::new(~[])
     };
     fcx.llenv.set(unsafe {
           llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
@@ -1810,10 +1300,9 @@ pub fn init_function<'a>(
                      fcx: &'a FunctionContext<'a>,
                      skip_retptr: bool,
                      output_type: ty::t,
-                     param_substs: Option<@param_substs>,
-                     opt_node_info: Option<NodeInfo>) {
+                     param_substs: Option<@param_substs>) {
     unsafe {
-        let entry_bcx = top_scope_block(fcx, opt_node_info);
+        let entry_bcx = fcx.new_temp_block("entry-block");
         Load(entry_bcx, C_null(Type::i8p()));
 
         fcx.entry_bcx.set(Some(entry_bcx));
@@ -1831,7 +1320,7 @@ pub fn init_function<'a>(
         }
     };
 
-    if !ty::type_is_voidish(fcx.ccx.tcx, substd_output_type) {
+    if !return_type_is_void(fcx.ccx, substd_output_type) {
         // If the function returns nil/bot, there is no real return
         // value, so do not set `llretptr`.
         if !skip_retptr || fcx.caller_expects_out_pointer {
@@ -1852,108 +1341,71 @@ pub fn new_fn_ctxt(ccx: @CrateContext,
                    -> FunctionContext {
     // FIXME(#11385): Do not call `init_function` here; it will typecheck
     // but segfault.
-    new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, sp)
+    new_fn_ctxt_detailed(ccx, path, llfndecl, -1, output_type, None, sp)
 }
 
 // NB: must keep 4 fns in sync:
 //
 //  - type_of_fn
-//  - create_llargs_for_fn_args.
+//  - create_datums_for_fn_args.
 //  - new_fn_ctxt
 //  - trans_args
 
-// create_llargs_for_fn_args: Creates a mapping from incoming arguments to
-// allocas created for them.
-//
-// When we translate a function, we need to map its incoming arguments to the
-// spaces that have been created for them (by code in the llallocas field of
-// the function's fn_ctxt).  create_llargs_for_fn_args populates the llargs
-// field of the fn_ctxt with
-fn create_llargs_for_fn_args(cx: &FunctionContext,
+fn arg_kind(cx: &FunctionContext, t: ty::t) -> datum::Rvalue {
+    use middle::trans::datum::{ByRef, ByValue};
+
+    datum::Rvalue {
+        mode: if arg_is_indirect(cx.ccx, t) { ByRef } else { ByValue }
+    }
+}
+
+// work around bizarre resolve errors
+type RvalueDatum = datum::Datum<datum::Rvalue>;
+type LvalueDatum = datum::Datum<datum::Lvalue>;
+
+// create_datums_for_fn_args: creates rvalue datums for `self` and each of the
+// incoming function arguments. These will later be stored into
+// appropriate lvalue datums.
+fn create_datums_for_fn_args(cx: &FunctionContext,
                              self_arg: Option<ty::t>,
                              arg_tys: &[ty::t])
-                             -> ~[datum::Datum] {
-    let _icx = push_ctxt("create_llargs_for_fn_args");
-
-    match self_arg {
-        Some(t) => {
-            cx.llself.set(Some(datum::Datum {
-                val: cx.llenv.get(),
-                ty: t,
-                mode: if arg_is_indirect(cx.ccx, t) {
-                    datum::ByRef(datum::ZeroMem)
-                } else {
-                    datum::ByValue
-                }
-            }));
-        }
-        None => {}
-    }
+                             -> (Option<RvalueDatum>, ~[RvalueDatum]) {
+    let _icx = push_ctxt("create_datums_for_fn_args");
+
+    let self_datum = self_arg.map(
+        |t| datum::Datum(cx.llenv.get(), t, arg_kind(cx, t)));
 
     // Return an array wrapping the ValueRefs that we get from
     // llvm::LLVMGetParam for each argument into datums.
-    arg_tys.iter().enumerate().map(|(i, &arg_ty)| {
-        let llarg = unsafe { llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint) };
-        datum::Datum {
-            val: llarg,
-            ty: arg_ty,
-            mode: if arg_is_indirect(cx.ccx, arg_ty) {
-                datum::ByRef(datum::ZeroMem)
-            } else {
-                datum::ByValue
-            }
-        }
-    }).collect()
+    let arg_datums = arg_tys.iter().enumerate().map(|(i, &arg_ty)| {
+            let llarg = unsafe {
+                llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint)
+            };
+            datum::Datum(llarg, arg_ty, arg_kind(cx, arg_ty))
+        }).collect();
+
+    (self_datum, arg_datums)
 }
 
 fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
+                            arg_scope: cleanup::CustomScopeIndex,
                             bcx: &'a Block<'a>,
                             args: &[ast::Arg],
-                            method: Option<&ast::Method>,
-                            raw_llargs: &[datum::Datum])
+                            self_datum: Option<RvalueDatum>,
+                            arg_datums: ~[RvalueDatum])
                             -> &'a Block<'a> {
-    debug!("copy_args_to_allocas: args=[{}]",
-           raw_llargs.map(|d| d.to_str(fcx.ccx)).connect(", "));
+    debug!("copy_args_to_allocas");
 
     let _icx = push_ctxt("copy_args_to_allocas");
     let mut bcx = bcx;
 
-    match fcx.llself.get() {
-        Some(slf) => {
-            let needs_indirection = if slf.mode.is_by_value() {
-                // FIXME(eddyb) #11445 Always needs indirection because of cleanup.
-                if true {
-                    true
-                } else {
-                    match method {
-                        Some(method) => {
-                            match method.explicit_self.node {
-                                ast::SelfValue(ast::MutMutable) => true,
-                                _ => false
-                            }
-                        }
-                        None => true
-                    }
-                }
-            } else {
-                false
-            };
-            let slf = if needs_indirection {
-                // HACK(eddyb) this is just slf.to_ref_datum(bcx) with a named alloca.
-                let alloc = alloc_ty(bcx, slf.ty, "__self");
-                Store(bcx, slf.val, alloc);
-                datum::Datum {
-                    val: alloc,
-                    ty: slf.ty,
-                    mode: datum::ByRef(datum::ZeroMem)
-                }
-            } else {
-                slf
-            };
-
+    let arg_scope_id = cleanup::CustomScope(arg_scope);
+    match self_datum {
+        Some(slf_rv) => {
+            let slf = unpack_datum!(
+                bcx, slf_rv.to_lvalue_datum_in_scope(bcx, "__self",
+                                                     arg_scope_id));
             fcx.llself.set(Some(slf));
-            slf.add_clean(bcx);
-
             if fcx.ccx.sess.opts.extra_debuginfo {
                 debuginfo::create_self_argument_metadata(bcx, slf.ty, slf.val);
             }
@@ -1961,24 +1413,7 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
         _ => {}
     }
 
-    for (i, &arg) in raw_llargs.iter().enumerate() {
-        let needs_indirection = if arg.mode.is_by_value() {
-            if fcx.ccx.sess.opts.extra_debuginfo {
-                true
-            } else {
-                // FIXME(eddyb) #11445 Always needs indirection because of cleanup.
-                if true {
-                    true
-                } else {
-                    match args[i].pat.node {
-                        ast::PatIdent(ast::BindByValue(ast::MutMutable), _, _) => true,
-                        _ => false
-                    }
-                }
-            }
-        } else {
-            false
-        };
+    for (i, arg_datum) in arg_datums.move_iter().enumerate() {
         // For certain mode/type combinations, the raw llarg values are passed
         // by value.  However, within the fn body itself, we want to always
         // have all locals and arguments be by-ref so that we can cancel the
@@ -1986,25 +1421,8 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
         // the argument would be passed by value, we store it into an alloca.
         // This alloca should be optimized away by LLVM's mem-to-reg pass in
         // the event it's not truly needed.
-        let arg = if needs_indirection {
-            // HACK(eddyb) this is just arg.to_ref_datum(bcx) with a named alloca.
-            let alloc = match args[i].pat.node {
-                ast::PatIdent(_, ref path, _) => {
-                    let name = ast_util::path_to_ident(path).name;
-                    alloc_ty(bcx, arg.ty, token::interner_get(name))
-                }
-                _ => alloc_ty(bcx, arg.ty, "__arg")
-            };
-            Store(bcx, arg.val, alloc);
-            datum::Datum {
-                val: alloc,
-                ty: arg.ty,
-                mode: datum::ByRef(datum::ZeroMem)
-            }
-        } else {
-            arg
-        };
-        bcx = _match::store_arg(bcx, args[i].pat, arg);
+
+        bcx = _match::store_arg(bcx, args[i].pat, arg_datum, arg_scope_id);
 
         if fcx.ccx.sess.opts.extra_debuginfo {
             debuginfo::create_argument_metadata(bcx, &args[i]);
@@ -2073,7 +1491,6 @@ pub fn trans_closure(ccx: @CrateContext,
                      self_arg: Option<ty::t>,
                      param_substs: Option<@param_substs>,
                      id: ast::NodeId,
-                     method: Option<&ast::Method>,
                      _attributes: &[ast::Attribute],
                      output_type: ty::t,
                      maybe_load_env: |&FunctionContext|) {
@@ -2085,14 +1502,17 @@ pub fn trans_closure(ccx: @CrateContext,
     debug!("trans_closure(..., param_substs={})",
            param_substs.repr(ccx.tcx));
 
-    let fcx = new_fn_ctxt_w_id(ccx,
-                               path,
-                               llfndecl,
-                               id,
-                               output_type,
-                               param_substs,
-                               Some(body.span));
-    init_function(&fcx, false, output_type, param_substs, body.info());
+    let fcx = new_fn_ctxt_detailed(ccx,
+                                   path,
+                                   llfndecl,
+                                   id,
+                                   output_type,
+                                   param_substs,
+                                   Some(body.span));
+    init_function(&fcx, false, output_type, param_substs);
+
+    // cleanup scope for the incoming arguments
+    let arg_scope = fcx.push_custom_cleanup_scope();
 
     // Create the first basic block in the function and keep a handle on it to
     //  pass to finish_fn later.
@@ -2102,9 +1522,11 @@ pub fn trans_closure(ccx: @CrateContext,
 
     // Set up arguments to the function.
     let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
-    let raw_llargs = create_llargs_for_fn_args(&fcx, self_arg, arg_tys);
+    let (self_datum, arg_datums) =
+        create_datums_for_fn_args(&fcx, self_arg, arg_tys);
 
-    bcx = copy_args_to_allocas(&fcx, bcx, decl.inputs, method, raw_llargs);
+    bcx = copy_args_to_allocas(&fcx, arg_scope, bcx,
+                               decl.inputs, self_datum, arg_datums);
 
     maybe_load_env(&fcx);
 
@@ -2117,7 +1539,7 @@ pub fn trans_closure(ccx: @CrateContext,
     // translation calls that don't have a return value (trans_crate,
     // trans_mod, trans_item, et cetera) and those that do
     // (trans_block, trans_expr, et cetera).
-    if body.expr.is_none() || ty::type_is_voidish(bcx.tcx(), block_ty) {
+    if body.expr.is_none() || type_is_zero_size(bcx.ccx(), block_ty) {
         bcx = controlflow::trans_block(bcx, body, expr::Ignore);
     } else {
         let dest = expr::SaveIn(fcx.llretptr.get().unwrap());
@@ -2125,8 +1547,15 @@ pub fn trans_closure(ccx: @CrateContext,
     }
 
     match fcx.llreturn.get() {
-        Some(llreturn) => cleanup_and_Br(bcx, bcx_top, llreturn),
-        None => bcx = cleanup_block(bcx, Some(bcx_top.llbb))
+        Some(_) => {
+            Br(bcx, fcx.return_exit_block());
+            fcx.pop_custom_cleanup_scope(arg_scope);
+        }
+        None => {
+            // Microoptimization writ large: avoid creating a separate
+            // llreturn basic block
+            bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
+        }
     };
 
     // Put return block after all other blocks.
@@ -2152,9 +1581,7 @@ pub fn trans_fn(ccx: @CrateContext,
                 self_arg: Option<ty::t>,
                 param_substs: Option<@param_substs>,
                 id: ast::NodeId,
-                method: Option<&ast::Method>,
                 attrs: &[ast::Attribute]) {
-
     let the_path_str = path_str(ccx.sess, path);
     let _s = StatRecorder::new(ccx, the_path_str);
     debug!("trans_fn(self_arg={:?}, param_substs={})",
@@ -2170,44 +1597,15 @@ pub fn trans_fn(ccx: @CrateContext,
                   self_arg,
                   param_substs,
                   id,
-                  method,
                   attrs,
                   output_type,
                   |_fcx| { });
 }
 
-fn insert_synthetic_type_entries(bcx: &Block,
-                                 fn_args: &[ast::Arg],
-                                 arg_tys: &[ty::t]) {
-    /*!
-     * For tuple-like structs and enum-variants, we generate
-     * synthetic AST nodes for the arguments.  These have no types
-     * in the type table and no entries in the moves table,
-     * so the code in `copy_args_to_allocas` and `bind_irrefutable_pat`
-     * gets upset. This hack of a function bridges the gap by inserting types.
-     *
-     * This feels horrible. I think we should just have a special path
-     * for these functions and not try to use the generic code, but
-     * that's not the problem I'm trying to solve right now. - nmatsakis
-     */
-
-    let tcx = bcx.tcx();
-    for i in range(0u, fn_args.len()) {
-        debug!("setting type of argument {} (pat node {}) to {}",
-               i, fn_args[i].pat.id, bcx.ty_to_str(arg_tys[i]));
-
-        let pat_id = fn_args[i].pat.id;
-        let arg_ty = arg_tys[i];
-
-        let mut node_types = tcx.node_types.borrow_mut();
-        node_types.get().insert(pat_id as uint, arg_ty);
-    }
-}
-
 pub fn trans_enum_variant(ccx: @CrateContext,
                           _enum_id: ast::NodeId,
                           variant: &ast::Variant,
-                          args: &[ast::VariantArg],
+                          _args: &[ast::VariantArg],
                           disr: ty::Disr,
                           param_substs: Option<@param_substs>,
                           llfndecl: ValueRef) {
@@ -2216,14 +1614,13 @@ pub fn trans_enum_variant(ccx: @CrateContext,
     trans_enum_variant_or_tuple_like_struct(
         ccx,
         variant.node.id,
-        args,
         disr,
         param_substs,
         llfndecl);
 }
 
 pub fn trans_tuple_struct(ccx: @CrateContext,
-                          fields: &[ast::StructField],
+                          _fields: &[ast::StructField],
                           ctor_id: ast::NodeId,
                           param_substs: Option<@param_substs>,
                           llfndecl: ValueRef) {
@@ -2232,46 +1629,16 @@ pub fn trans_tuple_struct(ccx: @CrateContext,
     trans_enum_variant_or_tuple_like_struct(
         ccx,
         ctor_id,
-        fields,
         0,
         param_substs,
         llfndecl);
 }
 
-trait IdAndTy {
-    fn id(&self) -> ast::NodeId;
-    fn ty(&self) -> ast::P<ast::Ty>;
-}
-
-impl IdAndTy for ast::VariantArg {
-    fn id(&self) -> ast::NodeId { self.id }
-    fn ty(&self) -> ast::P<ast::Ty> { self.ty }
-}
-
-impl IdAndTy for ast::StructField {
-    fn id(&self) -> ast::NodeId { self.node.id }
-    fn ty(&self) -> ast::P<ast::Ty> { self.node.ty }
-}
-
-fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
-    ccx: @CrateContext,
-    ctor_id: ast::NodeId,
-    args: &[A],
-    disr: ty::Disr,
-    param_substs: Option<@param_substs>,
-    llfndecl: ValueRef) {
-    // Translate variant arguments to function arguments.
-    let fn_args = args.map(|varg| {
-        ast::Arg {
-            ty: varg.ty(),
-            pat: ast_util::ident_to_pat(
-                ccx.tcx.sess.next_node_id(),
-                codemap::DUMMY_SP,
-                special_idents::arg),
-            id: varg.id(),
-        }
-    });
-
+fn trans_enum_variant_or_tuple_like_struct(ccx: @CrateContext,
+                                           ctor_id: ast::NodeId,
+                                           disr: ty::Disr,
+                                           param_substs: Option<@param_substs>,
+                                           llfndecl: ValueRef) {
     let no_substs: &[ty::t] = [];
     let ty_param_substs = match param_substs {
         Some(ref substs) => {
@@ -2297,38 +1664,34 @@ fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
                  ty_to_str(ccx.tcx, ctor_ty)))
     };
 
-    let fcx = new_fn_ctxt_w_id(ccx,
-                               ~[],
-                               llfndecl,
-                               ctor_id,
-                               result_ty,
-                               param_substs,
-                               None);
-    init_function(&fcx, false, result_ty, param_substs, None);
+    let fcx = new_fn_ctxt_detailed(ccx,
+                                   ~[],
+                                   llfndecl,
+                                   ctor_id,
+                                   result_ty,
+                                   param_substs,
+                                   None);
+    init_function(&fcx, false, result_ty, param_substs);
 
     let arg_tys = ty::ty_fn_args(ctor_ty);
 
-    let raw_llargs = create_llargs_for_fn_args(&fcx, None, arg_tys);
+    let (_, arg_datums) = create_datums_for_fn_args(&fcx, None, arg_tys);
 
     let bcx = fcx.entry_bcx.get().unwrap();
 
-    insert_synthetic_type_entries(bcx, fn_args, arg_tys);
-    let bcx = copy_args_to_allocas(&fcx, bcx, fn_args, None, raw_llargs);
-
-    let repr = adt::represent_type(ccx, result_ty);
-    adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr);
-    for (i, fn_arg) in fn_args.iter().enumerate() {
-        let lldestptr = adt::trans_field_ptr(bcx,
-                                             repr,
-                                             fcx.llretptr.get().unwrap(),
-                                             disr,
-                                             i);
-        let llarg = {
-            let llargs = fcx.llargs.borrow();
-            llargs.get().get_copy(&fn_arg.pat.id)
-        };
-        llarg.move_to(bcx, datum::INIT, lldestptr);
+    if !type_is_zero_size(fcx.ccx, result_ty) {
+        let repr = adt::represent_type(ccx, result_ty);
+        adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr);
+        for (i, arg_datum) in arg_datums.move_iter().enumerate() {
+            let lldestptr = adt::trans_field_ptr(bcx,
+                                                 repr,
+                                                 fcx.llretptr.get().unwrap(),
+                                                 disr,
+                                                 i);
+            arg_datum.store_to(bcx, lldestptr);
+        }
     }
+
     finish_fn(&fcx, bcx);
 }
 
@@ -2397,7 +1760,6 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::Item) {
                      None,
                      None,
                      item.id,
-                     None,
                      item.attrs);
         } else {
             // Be sure to travel more than just one layer deep to catch nested
@@ -2535,13 +1897,13 @@ pub fn register_fn_llvmty(ccx: @CrateContext,
                           sym: ~str,
                           node_id: ast::NodeId,
                           cc: lib::llvm::CallConv,
-                          fn_ty: Type)
-                          -> ValueRef {
+                          fn_ty: Type,
+                          output: ty::t) -> ValueRef {
     debug!("register_fn_fuller creating fn for item {} with path {}",
            node_id,
            ast_map::path_to_str(item_path(ccx, &node_id), token::get_ident_interner()));
 
-    let llfn = decl_fn(ccx.llmod, sym, cc, fn_ty);
+    let llfn = decl_fn(ccx.llmod, sym, cc, fn_ty, output);
     finish_register_fn(ccx, sp, sym, node_id, llfn);
     llfn
 }
@@ -2573,7 +1935,7 @@ fn create_entry_fn(ccx: @CrateContext,
         let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()],
                                &ccx.int_type);
 
-        let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty);
+        let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty, ty::mk_nil());
         let llbb = "top".with_c_str(|buf| {
             unsafe {
                 llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
@@ -2977,7 +2339,8 @@ pub fn p2i(ccx: &CrateContext, v: ValueRef) -> ValueRef {
 macro_rules! ifn (
     ($intrinsics:ident, $name:expr, $args:expr, $ret:expr) => ({
         let name = $name;
-        let f = decl_cdecl_fn(llmod, name, Type::func($args, &$ret));
+        // HACK(eddyb) dummy output type, shouln't affect anything.
+        let f = decl_cdecl_fn(llmod, name, Type::func($args, &$ret), ty::mk_nil());
         $intrinsics.insert(name, f);
     })
 )
index 0dd0d1589ff5841ec3a6aaf09e17c01040d7c6e3..44410ae24b9e4b3a0bba5d39be627ddc6fabefc6 100644 (file)
@@ -24,6 +24,7 @@
 use std::libc::{c_uint, c_ulonglong, c_char};
 
 pub fn terminate(cx: &Block, _: &str) {
+    debug!("terminate({})", cx.to_str());
     cx.terminated.set(true);
 }
 
@@ -315,12 +316,16 @@ pub fn ArrayMalloc(cx: &Block, Ty: Type, Val: ValueRef) -> ValueRef {
 pub fn Alloca(cx: &Block, Ty: Type, name: &str) -> ValueRef {
     unsafe {
         if cx.unreachable.get() { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
-        let b = cx.fcx.ccx.builder();
-        b.position_before(cx.fcx.alloca_insert_pt.get().unwrap());
-        b.alloca(Ty, name)
+        AllocaFcx(cx.fcx, Ty, name)
     }
 }
 
+pub fn AllocaFcx(fcx: &FunctionContext, Ty: Type, name: &str) -> ValueRef {
+    let b = fcx.ccx.builder();
+    b.position_before(fcx.alloca_insert_pt.get().unwrap());
+    b.alloca(Ty, name)
+}
+
 pub fn ArrayAlloca(cx: &Block, Ty: Type, Val: ValueRef) -> ValueRef {
     unsafe {
         if cx.unreachable.get() { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
index c1451a8fe1e1218f98a51e921a996584c8554c34..27903e74e07a583281e8056d7c967a8ec707d3d4 100644 (file)
@@ -27,6 +27,8 @@
 use middle::trans::base::*;
 use middle::trans::build::*;
 use middle::trans::callee;
+use middle::trans::cleanup;
+use middle::trans::cleanup::CleanupMethods;
 use middle::trans::common;
 use middle::trans::common::*;
 use middle::trans::datum::*;
@@ -60,11 +62,10 @@ pub struct FnData {
 pub struct MethodData {
     llfn: ValueRef,
     llself: ValueRef,
-    temp_cleanup: Option<ValueRef>
 }
 
 pub enum CalleeData {
-    Closure(Datum),
+    Closure(Datum<Lvalue>),
     Fn(FnData),
     Method(MethodData)
 }
@@ -74,7 +75,7 @@ pub struct Callee<'a> {
     data: CalleeData
 }
 
-pub fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
+fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
     let _icx = push_ctxt("trans_callee");
     debug!("callee::trans(expr={})", expr.repr(bcx.tcx()));
 
@@ -90,13 +91,15 @@ pub fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
     return datum_callee(bcx, expr);
 
     fn datum_callee<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
-        let DatumBlock {bcx, datum} = expr::trans_to_datum(bcx, expr);
+        let DatumBlock {bcx: mut bcx, datum} = expr::trans(bcx, expr);
         match ty::get(datum.ty).sty {
             ty::ty_bare_fn(..) => {
-                let llval = datum.to_appropriate_llval(bcx);
+                let llval = datum.to_llscalarish(bcx);
                 return Callee {bcx: bcx, data: Fn(FnData {llfn: llval})};
             }
             ty::ty_closure(..) => {
+                let datum = unpack_datum!(
+                    bcx, datum.to_lvalue_datum(bcx, "callee", expr.id));
                 return Callee {bcx: bcx, data: Closure(datum)};
             }
             _ => {
@@ -458,10 +461,10 @@ pub fn trans_call<'a>(
                   -> &'a Block<'a> {
     let _icx = push_ctxt("trans_call");
     trans_call_inner(in_cx,
-                     call_ex.info(),
+                     Some(common::expr_info(call_ex)),
                      expr_ty(in_cx, f),
                      node_id_type(in_cx, id),
-                     |cx| trans(cx, f),
+                     |cx, _| trans(cx, f),
                      args,
                      Some(dest),
                      DontAutorefArg).bcx
@@ -481,10 +484,10 @@ pub fn trans_method_call<'a>(
            rcvr.repr(in_cx.tcx()));
     trans_call_inner(
         in_cx,
-        call_ex.info(),
+        Some(common::expr_info(call_ex)),
         node_id_type(in_cx, callee_id),
         expr_ty(in_cx, call_ex),
-        |cx| {
+        |cx, arg_cleanup_scope| {
             let origin_opt = {
                 let mut method_map = cx.ccx().maps.method_map.borrow_mut();
                 method_map.get().find_copy(&call_ex.id)
@@ -495,7 +498,11 @@ pub fn trans_method_call<'a>(
                            call_ex.repr(in_cx.tcx()),
                            origin.repr(in_cx.tcx()));
 
-                    meth::trans_method_callee(cx, callee_id, rcvr, origin)
+                    meth::trans_method_callee(cx,
+                                              callee_id,
+                                              rcvr,
+                                              origin,
+                                              arg_cleanup_scope)
                 }
                 None => {
                     cx.tcx().sess.span_bug(call_ex.span, "method call expr wasn't in method map")
@@ -523,7 +530,7 @@ pub fn trans_lang_call<'a>(
                              None,
                              fty,
                              rty,
-                             |bcx| {
+                             |bcx, _| {
                                 trans_fn_ref_with_vtables_to_callee(bcx,
                                                                     did,
                                                                     0,
@@ -551,8 +558,11 @@ pub fn trans_lang_call_with_type_params<'a>(
 
     let rty = ty::ty_fn_ret(fty);
     return callee::trans_call_inner(
-        bcx, None, fty, rty,
-        |bcx| {
+        bcx,
+        None,
+        fty,
+        rty,
+        |bcx, _| {
             let callee =
                 trans_fn_ref_with_vtables_to_callee(bcx, did, 0,
                                                     type_params,
@@ -577,11 +587,13 @@ pub fn trans_lang_call_with_type_params<'a>(
 }
 
 pub fn trans_call_inner<'a>(
-                        in_cx: &'a Block<'a>,
+                        bcx: &'a Block<'a>,
                         call_info: Option<NodeInfo>,
                         callee_ty: ty::t,
                         ret_ty: ty::t,
-                        get_callee: |&'a Block<'a>| -> Callee<'a>,
+                        get_callee: |bcx: &'a Block<'a>,
+                                     arg_cleanup_scope: cleanup::ScopeId|
+                                     -> Callee<'a>,
                         args: CallArgs,
                         dest: Option<expr::Dest>,
                         autoref_arg: AutorefArg)
@@ -593,171 +605,180 @@ pub fn trans_call_inner<'a>(
      * this into two functions seems like a good idea).
      *
      * In particular, for lang items, it is invoked with a dest of
-     * None, and
+     * None, and in that case the return value contains the result of
+     * the fn. The lang item must not return a structural type or else
+     * all heck breaks loose.
+     *
+     * For non-lang items, `dest` is always Some, and hence the result
+     * is written into memory somewhere. Nonetheless we return the
+     * actual return value of the function.
      */
 
-
-    base::with_scope_result(in_cx, call_info, "call", |cx| {
-        let callee = get_callee(cx);
-        let mut bcx = callee.bcx;
-        let ccx = cx.ccx();
-
-        let (llfn, llenv) = unsafe {
-            match callee.data {
-                Fn(d) => {
-                    (d.llfn, llvm::LLVMGetUndef(Type::opaque_box(ccx).ptr_to().to_ref()))
-                }
-                Method(d) => {
-                    // Weird but true: we pass self in the *environment* slot!
-                    (d.llfn, d.llself)
-                }
-                Closure(d) => {
-                    // Closures are represented as (llfn, llclosure) pair:
-                    // load the requisite values out.
-                    let pair = d.to_ref_llval(bcx);
-                    let llfn = GEPi(bcx, pair, [0u, abi::fn_field_code]);
-                    let llfn = Load(bcx, llfn);
-                    let llenv = GEPi(bcx, pair, [0u, abi::fn_field_box]);
-                    let llenv = Load(bcx, llenv);
-                    (llfn, llenv)
-                }
+    // Introduce a temporary cleanup scope that will contain cleanups
+    // for the arguments while they are being evaluated. The purpose
+    // this cleanup is to ensure that, should a failure occur while
+    // evaluating argument N, the values for arguments 0...N-1 are all
+    // cleaned up. If no failure occurs, the values are handed off to
+    // the callee, and hence none of the cleanups in this temporary
+    // scope will ever execute.
+    let fcx = bcx.fcx;
+    let ccx = fcx.ccx;
+    let arg_cleanup_scope = fcx.push_custom_cleanup_scope();
+
+    let callee = get_callee(bcx, cleanup::CustomScope(arg_cleanup_scope));
+    let mut bcx = callee.bcx;
+
+    let (llfn, llenv) = unsafe {
+        match callee.data {
+            Fn(d) => {
+                (d.llfn, llvm::LLVMGetUndef(Type::opaque_box(ccx).ptr_to().to_ref()))
             }
-        };
-
-        let abi = match ty::get(callee_ty).sty {
-            ty::ty_bare_fn(ref f) => f.abis,
-            _ => AbiSet::Rust()
-        };
-        let is_rust_fn =
-            abi.is_rust() ||
-            abi.is_intrinsic();
-
-        // Generate a location to store the result. If the user does
-        // not care about the result, just make a stack slot.
-        let opt_llretslot = match dest {
-            None => {
-                assert!(!type_of::return_uses_outptr(in_cx.ccx(), ret_ty));
-                None
+            Method(d) => {
+                // Weird but true: we pass self in the *environment* slot!
+                (d.llfn, d.llself)
             }
-            Some(expr::SaveIn(dst)) => Some(dst),
-            Some(expr::Ignore) => {
-                if !ty::type_is_voidish(in_cx.tcx(), ret_ty) {
-                    Some(alloc_ty(bcx, ret_ty, "__llret"))
-                } else {
-                    unsafe {
-                        Some(llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()))
-                    }
-                }
+            Closure(d) => {
+                // Closures are represented as (llfn, llclosure) pair:
+                // load the requisite values out.
+                let pair = d.to_llref();
+                let llfn = GEPi(bcx, pair, [0u, abi::fn_field_code]);
+                let llfn = Load(bcx, llfn);
+                let llenv = GEPi(bcx, pair, [0u, abi::fn_field_box]);
+                let llenv = Load(bcx, llenv);
+                (llfn, llenv)
             }
-        };
-
-        let mut llresult = unsafe {
-            llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
-        };
+        }
+    };
 
-        // The code below invokes the function, using either the Rust
-        // conventions (if it is a rust fn) or the native conventions
-        // (otherwise).  The important part is that, when all is sad
-        // and done, either the return value of the function will have been
-        // written in opt_llretslot (if it is Some) or `llresult` will be
-        // set appropriately (otherwise).
-        if is_rust_fn {
-            let mut llargs = ~[];
-
-            // Push the out-pointer if we use an out-pointer for this
-            // return type, otherwise push "undef".
-            if type_of::return_uses_outptr(in_cx.ccx(), ret_ty) {
-                llargs.push(opt_llretslot.unwrap());
+    let abi = match ty::get(callee_ty).sty {
+        ty::ty_bare_fn(ref f) => f.abis,
+        _ => AbiSet::Rust()
+    };
+    let is_rust_fn =
+        abi.is_rust() ||
+        abi.is_intrinsic();
+
+    // Generate a location to store the result. If the user does
+    // not care about the result, just make a stack slot.
+    let opt_llretslot = match dest {
+        None => {
+            assert!(!type_of::return_uses_outptr(ccx, ret_ty));
+            None
+        }
+        Some(expr::SaveIn(dst)) => Some(dst),
+        Some(expr::Ignore) => {
+            if !type_is_zero_size(ccx, ret_ty) {
+                Some(alloc_ty(bcx, ret_ty, "__llret"))
+            } else {
+                let llty = type_of::type_of(ccx, ret_ty);
+                Some(C_undef(llty.ptr_to()))
             }
+        }
+    };
+
+    let mut llresult = unsafe {
+        llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
+    };
 
-            // Push the environment.
-            llargs.push(llenv);
+    // The code below invokes the function, using either the Rust
+    // conventions (if it is a rust fn) or the native conventions
+    // (otherwise).  The important part is that, when all is sad
+    // and done, either the return value of the function will have been
+    // written in opt_llretslot (if it is Some) or `llresult` will be
+    // set appropriately (otherwise).
+    if is_rust_fn {
+        let mut llargs = ~[];
+
+        // Push the out-pointer if we use an out-pointer for this
+        // return type, otherwise push "undef".
+        if type_of::return_uses_outptr(ccx, ret_ty) {
+            llargs.push(opt_llretslot.unwrap());
+        }
 
-            // Push the arguments.
-            bcx = trans_args(bcx, args, callee_ty,
-                             autoref_arg, &mut llargs);
+        // Push the environment.
+        llargs.push(llenv);
 
-            // Now that the arguments have finished evaluating, we
-            // need to revoke the cleanup for the self argument
-            match callee.data {
-                Method(d) => {
-                    for &v in d.temp_cleanup.iter() {
-                        revoke_clean(bcx, v);
-                    }
-                }
-                _ => {}
-            }
+        // Push the arguments.
+        bcx = trans_args(bcx, args, callee_ty,
+                         autoref_arg, &mut llargs,
+                         cleanup::CustomScope(arg_cleanup_scope));
 
-            // A function pointer is called without the declaration available, so we have to apply
-            // any attributes with ABI implications directly to the call instruction. Right now, the
-            // only attribute we need to worry about is `sret`.
-            let mut attrs = ~[];
-            if type_of::return_uses_outptr(in_cx.ccx(), ret_ty) {
-                attrs.push((1, StructRetAttribute));
-            }
+        fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
+
+        // A function pointer is called without the declaration
+        // available, so we have to apply any attributes with ABI
+        // implications directly to the call instruction. Right now,
+        // the only attribute we need to worry about is `sret`.
+        let mut attrs = ~[];
+        if type_of::return_uses_outptr(ccx, ret_ty) {
+            attrs.push((1, StructRetAttribute));
+        }
 
-            // The `noalias` attribute on the return value is useful to a function ptr caller.
-            match ty::get(ret_ty).sty {
-                // `~` pointer return values never alias because ownership is transferred
-                ty::ty_uniq(..) |
+        // The `noalias` attribute on the return value is useful to a
+        // function ptr caller.
+        match ty::get(ret_ty).sty {
+            // `~` pointer return values never alias because ownership
+            // is transferred
+            ty::ty_uniq(..) |
                 ty::ty_vec(_, ty::vstore_uniq) => {
-                    attrs.push((0, NoAliasAttribute));
-                }
-                _ => ()
+                attrs.push((0, NoAliasAttribute));
             }
+            _ => ()
+        }
 
-            // Invoke the actual rust fn and update bcx/llresult.
-            let (llret, b) = base::invoke(bcx, llfn, llargs, attrs, call_info);
-            bcx = b;
-            llresult = llret;
-
-            // If the Rust convention for this type is return via
-            // the return value, copy it into llretslot.
-            match opt_llretslot {
-                Some(llretslot) => {
-                    if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
-                        !ty::type_is_voidish(bcx.tcx(), ret_ty)
-                    {
-                        Store(bcx, llret, llretslot);
-                    }
+        // Invoke the actual rust fn and update bcx/llresult.
+        let (llret, b) = base::invoke(bcx, llfn, llargs, attrs, call_info);
+        bcx = b;
+        llresult = llret;
+
+        // If the Rust convention for this type is return via
+        // the return value, copy it into llretslot.
+        match opt_llretslot {
+            Some(llretslot) => {
+                if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
+                    !type_is_zero_size(bcx.ccx(), ret_ty)
+                {
+                    Store(bcx, llret, llretslot);
                 }
-                None => {}
             }
-        } else {
-            // Lang items are the only case where dest is None, and
-            // they are always Rust fns.
-            assert!(dest.is_some());
-
-            let mut llargs = ~[];
-            bcx = trans_args(bcx, args, callee_ty,
-                             autoref_arg, &mut llargs);
-            let arg_tys = match args {
-                ArgExprs(a) => a.iter().map(|x| expr_ty(bcx, *x)).collect(),
-                ArgVals(_) => fail!("expected arg exprs.")
-            };
-            bcx = foreign::trans_native_call(bcx, callee_ty,
-                                             llfn, opt_llretslot.unwrap(), llargs, arg_tys);
+            None => {}
         }
+    } else {
+        // Lang items are the only case where dest is None, and
+        // they are always Rust fns.
+        assert!(dest.is_some());
+
+        let mut llargs = ~[];
+        bcx = trans_args(bcx, args, callee_ty,
+                         autoref_arg, &mut llargs,
+                         cleanup::CustomScope(arg_cleanup_scope));
+        fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
+        let arg_tys = match args {
+            ArgExprs(a) => a.iter().map(|x| expr_ty(bcx, *x)).collect(),
+            ArgVals(_) => fail!("expected arg exprs.")
+        };
+        bcx = foreign::trans_native_call(bcx, callee_ty,
+                                         llfn, opt_llretslot.unwrap(), llargs, arg_tys);
+    }
 
-        // If the caller doesn't care about the result of this fn call,
-        // drop the temporary slot we made.
-        match dest {
-            None => {
-                assert!(!type_of::return_uses_outptr(bcx.ccx(), ret_ty));
-            }
-            Some(expr::Ignore) => {
-                // drop the value if it is not being saved.
-                bcx = glue::drop_ty(bcx, opt_llretslot.unwrap(), ret_ty);
-            }
-            Some(expr::SaveIn(_)) => { }
+    // If the caller doesn't care about the result of this fn call,
+    // drop the temporary slot we made.
+    match dest {
+        None => {
+            assert!(!type_of::return_uses_outptr(bcx.ccx(), ret_ty));
         }
-
-        if ty::type_is_bot(ret_ty) {
-            Unreachable(bcx);
+        Some(expr::Ignore) => {
+            // drop the value if it is not being saved.
+            bcx = glue::drop_ty(bcx, opt_llretslot.unwrap(), ret_ty);
         }
+        Some(expr::SaveIn(_)) => { }
+    }
 
-        rslt(bcx, llresult)
-    })
+    if ty::type_is_bot(ret_ty) {
+        Unreachable(bcx);
+    }
+
+    rslt(bcx, llresult)
 }
 
 pub enum CallArgs<'a> {
@@ -770,10 +791,11 @@ pub fn trans_args<'a>(
                   args: CallArgs,
                   fn_ty: ty::t,
                   autoref_arg: AutorefArg,
-                  llargs: &mut ~[ValueRef])
-                  -> &'a Block<'a> {
+                  llargs: &mut ~[ValueRef],
+                  arg_cleanup_scope: cleanup::ScopeId)
+                  -> &'a Block<'a>
+{
     let _icx = push_ctxt("trans_args");
-    let mut temp_cleanups = ~[];
     let arg_tys = ty::ty_fn_args(fn_ty);
     let variadic = ty::fn_is_variadic(fn_ty);
 
@@ -796,7 +818,7 @@ pub fn trans_args<'a>(
                 trans_arg_expr(bcx,
                                arg_ty,
                                *arg_expr,
-                               &mut temp_cleanups,
+                               arg_cleanup_scope,
                                autoref_arg)
             });
             llargs.push(arg_val);
@@ -807,13 +829,6 @@ pub fn trans_args<'a>(
       }
     }
 
-    // now that all arguments have been successfully built, we can revoke any
-    // temporary cleanups, as they are only needed if argument construction
-    // should fail (for example, cleanup of copy mode args).
-    for c in temp_cleanups.iter() {
-        revoke_clean(bcx, *c)
-    }
-
     bcx
 }
 
@@ -822,16 +837,15 @@ pub enum AutorefArg {
     DoAutorefArg
 }
 
-// temp_cleanups: cleanups that should run only if failure occurs before the
-// call takes place:
 pub fn trans_arg_expr<'a>(
                       bcx: &'a Block<'a>,
                       formal_arg_ty: ty::t,
                       arg_expr: &ast::Expr,
-                      temp_cleanups: &mut ~[ValueRef],
+                      arg_cleanup_scope: cleanup::ScopeId,
                       autoref_arg: AutorefArg)
                       -> Result<'a> {
     let _icx = push_ctxt("trans_arg_expr");
+    let mut bcx = bcx;
     let ccx = bcx.ccx();
 
     debug!("trans_arg_expr(formal_arg_ty=({}), arg_expr={})",
@@ -839,14 +853,13 @@ pub fn trans_arg_expr<'a>(
            arg_expr.repr(bcx.tcx()));
 
     // translate the arg expr to a datum
-    let arg_datumblock = expr::trans_to_datum(bcx, arg_expr);
-    let arg_datum = arg_datumblock.datum;
-    let bcx = arg_datumblock.bcx;
+    let arg_datum = unpack_datum!(bcx, expr::trans(bcx, arg_expr));
+    let arg_datum_ty = arg_datum.ty;
 
     debug!("   arg datum: {}", arg_datum.to_str(bcx.ccx()));
 
     let mut val;
-    if ty::type_is_bot(arg_datum.ty) {
+    if ty::type_is_bot(arg_datum_ty) {
         // For values of type _|_, we generate an
         // "undef" value, as such a value should never
         // be inspected. It's important for the value
@@ -859,34 +872,31 @@ pub fn trans_arg_expr<'a>(
         // FIXME(#3548) use the adjustments table
         match autoref_arg {
             DoAutorefArg => {
-                val = arg_datum.to_ref_llval(bcx);
+                // We will pass argument by reference
+                // We want an lvalue, so that we can pass by reference and
+                let arg_datum = unpack_datum!(
+                    bcx, arg_datum.to_lvalue_datum(bcx, "arg", arg_expr.id));
+                val = arg_datum.val;
             }
             DontAutorefArg => {
-                let need_scratch = ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
-                    (bcx.expr_is_lval(arg_expr) &&
-                     arg_datum.appropriate_mode(bcx.ccx()).is_by_ref());
-
-                let arg_datum = if need_scratch {
-                    let scratch = scratch_datum(bcx, arg_datum.ty, "__self", false);
-                    arg_datum.store_to_datum(bcx, INIT, scratch);
-
-                    // Technically, ownership of val passes to the callee.
-                    // However, we must cleanup should we fail before the
-                    // callee is actually invoked.
-                    scratch.add_clean(bcx);
-                    temp_cleanups.push(scratch.val);
-
-                    scratch
-                } else {
-                    arg_datum
-                };
-
-                debug!("by copy arg with type {}", bcx.ty_to_str(arg_datum.ty));
-                val = arg_datum.to_appropriate_llval(bcx);
+                // Make this an rvalue, since we are going to be
+                // passing ownership.
+                let arg_datum = unpack_datum!(
+                    bcx, arg_datum.to_rvalue_datum(bcx, "arg"));
+
+                // Now that arg_datum is owned, get it into the appropriate
+                // mode (ref vs value).
+                let arg_datum = unpack_datum!(
+                    bcx, arg_datum.to_appropriate_datum(bcx));
+
+                // Technically, ownership of val passes to the callee.
+                // However, we must cleanup should we fail before the
+                // callee is actually invoked.
+                val = arg_datum.add_clean(bcx.fcx, arg_cleanup_scope);
             }
         }
 
-        if formal_arg_ty != arg_datum.ty {
+        if formal_arg_ty != arg_datum_ty {
             // this could happen due to e.g. subtyping
             let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
             debug!("casting actual type ({}) to match formal ({})",
diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs
new file mode 100644 (file)
index 0000000..6fed396
--- /dev/null
@@ -0,0 +1,948 @@
+// 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.
+
+/*!
+ * Code pertaining to cleanup of temporaries as well as execution of
+ * drop glue. See discussion in `doc.rs` for a high-level summary.
+ */
+
+use lib::llvm::{BasicBlockRef, ValueRef};
+use middle::lang_items::{EhPersonalityLangItem};
+use middle::trans::base;
+use middle::trans::build;
+use middle::trans::callee;
+use middle::trans::common;
+use middle::trans::common::{Block, FunctionContext};
+use middle::trans::glue;
+use middle::trans::type_::Type;
+use middle::ty;
+use syntax::ast;
+use syntax::ast_map;
+use syntax::parse::token;
+use syntax::opt_vec;
+use syntax::opt_vec::OptVec;
+use util::ppaux::Repr;
+
+pub struct CleanupScope<'a> {
+    // The id of this cleanup scope. If the id is None,
+    // this is a *temporary scope* that is pushed during trans to
+    // cleanup miscellaneous garbage that trans may generate whose
+    // lifetime is a subset of some expression.  See module doc for
+    // more details.
+    kind: CleanupScopeKind<'a>,
+
+    // Cleanups to run upon scope exit.
+    cleanups: OptVec<~Cleanup>,
+
+    cached_early_exits: OptVec<CachedEarlyExit>,
+    cached_landing_pad: Option<BasicBlockRef>,
+}
+
+pub struct CustomScopeIndex {
+    priv index: uint
+}
+
+pub static EXIT_BREAK: uint = 0;
+pub static EXIT_LOOP: uint = 1;
+pub static EXIT_MAX: uint = 2;
+
+enum CleanupScopeKind<'a> {
+    CustomScopeKind,
+    AstScopeKind(ast::NodeId),
+    LoopScopeKind(ast::NodeId, [&'a Block<'a>, ..EXIT_MAX])
+}
+
+#[deriving(Eq)]
+enum EarlyExitLabel {
+    UnwindExit,
+    ReturnExit,
+    LoopExit(ast::NodeId, uint)
+}
+
+struct CachedEarlyExit {
+    label: EarlyExitLabel,
+    cleanup_block: BasicBlockRef,
+}
+
+pub trait Cleanup {
+    fn clean_on_unwind(&self) -> bool;
+    fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a>;
+}
+
+pub enum ScopeId {
+    AstScope(ast::NodeId),
+    CustomScope(CustomScopeIndex)
+}
+
+impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
+    fn push_ast_cleanup_scope(&self, id: ast::NodeId) {
+        /*!
+         * Invoked when we start to trans the code contained
+         * within a new cleanup scope.
+         */
+
+        debug!("push_ast_cleanup_scope({})",
+               ast_map::node_id_to_str(self.ccx.tcx.items, id,
+                                       token::get_ident_interner()));
+
+        // FIXME(#2202) -- currently closure bodies have a parent
+        // region, which messes up the assertion below, since there
+        // are no cleanup scopes on the stack at the start of
+        // trans'ing a closure body.  I think though that this should
+        // eventually be fixed by closure bodies not having a parent
+        // region, though that's a touch unclear, and it might also be
+        // better just to narrow this assertion more (i.e., by
+        // excluding id's that correspond to closure bodies only). For
+        // now we just say that if there is already an AST scope on the stack,
+        // this new AST scope had better be its immediate child.
+        let top_scope = self.top_ast_scope();
+        if top_scope.is_some() {
+            assert_eq!(self.ccx.tcx.region_maps.opt_encl_scope(id), top_scope);
+        }
+
+        self.push_scope(CleanupScope::new(AstScopeKind(id)));
+    }
+
+    fn push_loop_cleanup_scope(&self,
+                               id: ast::NodeId,
+                               exits: [&'a Block<'a>, ..EXIT_MAX]) {
+        debug!("push_loop_cleanup_scope({})",
+               ast_map::node_id_to_str(self.ccx.tcx.items, id,
+                                       token::get_ident_interner()));
+        assert_eq!(Some(id), self.top_ast_scope());
+
+        self.push_scope(CleanupScope::new(LoopScopeKind(id, exits)));
+    }
+
+    fn push_custom_cleanup_scope(&self) -> CustomScopeIndex {
+        let index = self.scopes_len();
+        debug!("push_custom_cleanup_scope(): {}", index);
+        self.push_scope(CleanupScope::new(CustomScopeKind));
+        CustomScopeIndex { index: index }
+    }
+
+    fn pop_and_trans_ast_cleanup_scope(&self,
+                                       bcx: &'a Block<'a>,
+                                       cleanup_scope: ast::NodeId)
+                                       -> &'a Block<'a> {
+        /*!
+         * Removes the cleanup scope for id `cleanup_scope`, which
+         * must be at the top of the cleanup stack, and generates the
+         * code to do its cleanups for normal exit.
+         */
+
+        debug!("pop_and_trans_ast_cleanup_scope({})",
+               ast_map::node_id_to_str(self.ccx.tcx.items, cleanup_scope,
+                                       token::get_ident_interner()));
+
+        assert!(self.top_scope(|s| s.kind.is_ast_with_id(cleanup_scope)));
+
+        let scope = self.pop_scope();
+        self.trans_scope_cleanups(bcx, &scope)
+
+    }
+
+    fn pop_loop_cleanup_scope(&self,
+                              cleanup_scope: ast::NodeId) {
+        /*!
+         * Removes the loop cleanup scope for id `cleanup_scope`, which
+         * must be at the top of the cleanup stack. Does not generate
+         * any cleanup code, since loop scopes should exit by
+         * branching to a block generated by `normal_exit_block`.
+         */
+
+        debug!("pop_loop_cleanup_scope({})",
+               ast_map::node_id_to_str(self.ccx.tcx.items, cleanup_scope,
+                                       token::get_ident_interner()));
+
+        assert!(self.top_scope(|s| s.kind.is_loop_with_id(cleanup_scope)));
+
+        let _ = self.pop_scope();
+    }
+
+    fn pop_custom_cleanup_scope(&self,
+                                custom_scope: CustomScopeIndex) {
+        /*!
+         * Removes the top cleanup scope from the stack without
+         * executing its cleanups. The top cleanup scope must
+         * be the temporary scope `custom_scope`.
+         */
+
+        debug!("pop_custom_cleanup_scope({})", custom_scope.index);
+        assert!(self.is_valid_to_pop_custom_scope(custom_scope));
+        let _ = self.pop_scope();
+    }
+
+    fn pop_and_trans_custom_cleanup_scope(&self,
+                                        bcx: &'a Block<'a>,
+                                        custom_scope: CustomScopeIndex)
+                                        -> &'a Block<'a> {
+        /*!
+         * Removes the top cleanup scope from the stack, which must be
+         * a temporary scope, and generates the code to do its
+         * cleanups for normal exit.
+         */
+
+        debug!("pop_and_trans_custom_cleanup_scope({:?})", custom_scope);
+        assert!(self.is_valid_to_pop_custom_scope(custom_scope));
+
+        let scope = self.pop_scope();
+        self.trans_scope_cleanups(bcx, &scope)
+    }
+
+    fn top_loop_scope(&self) -> ast::NodeId {
+        /*!
+         * Returns the id of the top-most loop scope
+         */
+
+        let scopes = self.scopes.borrow();
+        for scope in scopes.get().iter().invert() {
+            match scope.kind {
+                LoopScopeKind(id, _) => {
+                    return id;
+                }
+                _ => {}
+            }
+        }
+        self.ccx.tcx.sess.bug("No loop scope found");
+    }
+
+    fn normal_exit_block(&self,
+                         cleanup_scope: ast::NodeId,
+                         exit: uint) -> BasicBlockRef {
+        /*!
+         * Returns a block to branch to which will perform all pending
+         * cleanups and then break/continue (depending on `exit`) out
+         * of the loop with id `cleanup_scope`
+         */
+
+        self.trans_cleanups_to_exit_scope(LoopExit(cleanup_scope, exit))
+    }
+
+    fn return_exit_block(&self) -> BasicBlockRef {
+        /*!
+         * Returns a block to branch to which will perform all pending
+         * cleanups and then return from this function
+         */
+
+        self.trans_cleanups_to_exit_scope(ReturnExit)
+    }
+
+    fn schedule_drop_mem(&self,
+                         cleanup_scope: ScopeId,
+                         val: ValueRef,
+                         ty: ty::t) {
+        /*!
+         * Schedules a (deep) drop of `val`, which is a pointer to an
+         * instance of `ty`
+         */
+
+        if !ty::type_needs_drop(self.ccx.tcx, ty) { return; }
+        let drop = ~DropValue {
+            is_immediate: false,
+            on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx, ty),
+            val: val,
+            ty: ty
+        };
+
+        debug!("schedule_drop_mem({:?}, val={}, ty={})",
+               cleanup_scope,
+               self.ccx.tn.val_to_str(val),
+               ty.repr(self.ccx.tcx));
+
+        self.schedule_clean(cleanup_scope, drop as ~Cleanup);
+    }
+
+    fn schedule_drop_immediate(&self,
+                               cleanup_scope: ScopeId,
+                               val: ValueRef,
+                               ty: ty::t) {
+        /*!
+         * Schedules a (deep) drop of `val`, which is an instance of `ty`
+         */
+
+        if !ty::type_needs_drop(self.ccx.tcx, ty) { return; }
+        let drop = ~DropValue {
+            is_immediate: true,
+            on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx, ty),
+            val: val,
+            ty: ty
+        };
+
+        debug!("schedule_drop_immediate({:?}, val={}, ty={})",
+               cleanup_scope,
+               self.ccx.tn.val_to_str(val),
+               ty.repr(self.ccx.tcx));
+
+        self.schedule_clean(cleanup_scope, drop as ~Cleanup);
+    }
+
+    fn schedule_free_value(&self,
+                           cleanup_scope: ScopeId,
+                           val: ValueRef,
+                           heap: common::heap) {
+        /*!
+         * Schedules a call to `free(val)`. Note that this is a shallow
+         * operation.
+         */
+
+        let drop = ~FreeValue { ptr: val, heap: heap };
+
+        debug!("schedule_free_value({:?}, val={}, heap={:?})",
+               cleanup_scope,
+               self.ccx.tn.val_to_str(val),
+               heap);
+
+        self.schedule_clean(cleanup_scope, drop as ~Cleanup);
+    }
+
+    fn schedule_clean(&self,
+                      cleanup_scope: ScopeId,
+                      cleanup: ~Cleanup) {
+        match cleanup_scope {
+            AstScope(id) => self.schedule_clean_in_ast_scope(id, cleanup),
+            CustomScope(id) => self.schedule_clean_in_custom_scope(id, cleanup),
+        }
+    }
+
+    fn schedule_clean_in_ast_scope(&self,
+                                   cleanup_scope: ast::NodeId,
+                                   cleanup: ~Cleanup) {
+        /*!
+         * Schedules a cleanup to occur upon exit from `cleanup_scope`.
+         * If `cleanup_scope` is not provided, then the cleanup is scheduled
+         * in the topmost scope, which must be a temporary scope.
+         */
+
+        debug!("schedule_clean_in_ast_scope(cleanup_scope={:?})",
+               cleanup_scope);
+
+        let mut scopes = self.scopes.borrow_mut();
+        for scope in scopes.get().mut_iter().invert() {
+            if scope.kind.is_ast_with_id(cleanup_scope) {
+                scope.cleanups.push(cleanup);
+                scope.clear_cached_exits();
+                return;
+            } else {
+                // will be adding a cleanup to some enclosing scope
+                scope.clear_cached_exits();
+            }
+        }
+
+        self.ccx.tcx.sess.bug(
+            format!("No cleanup scope {} found",
+                    ast_map::node_id_to_str(self.ccx.tcx.items, cleanup_scope,
+                                            token::get_ident_interner())));
+    }
+
+    fn schedule_clean_in_custom_scope(&self,
+                                      custom_scope: CustomScopeIndex,
+                                      cleanup: ~Cleanup) {
+        /*!
+         * Schedules a cleanup to occur in the top-most scope,
+         * which must be a temporary scope.
+         */
+
+        debug!("schedule_clean_in_custom_scope(custom_scope={})",
+               custom_scope.index);
+
+        assert!(self.is_valid_custom_scope(custom_scope));
+
+        let mut scopes = self.scopes.borrow_mut();
+        let scope = &mut scopes.get()[custom_scope.index];
+        scope.cleanups.push(cleanup);
+        scope.clear_cached_exits();
+    }
+
+    fn needs_invoke(&self) -> bool {
+        /*!
+         * Returns true if there are pending cleanups that should
+         * execute on failure.
+         */
+
+        let scopes = self.scopes.borrow();
+        scopes.get().iter().invert().any(|s| s.needs_invoke())
+    }
+
+    fn get_landing_pad(&self) -> BasicBlockRef {
+        /*!
+         * Returns a basic block to branch to in the event of a failure.
+         * This block will run the failure cleanups and eventually
+         * invoke the LLVM `Resume` instruction.
+         */
+
+        let _icx = base::push_ctxt("get_landing_pad");
+
+        debug!("get_landing_pad");
+
+        let orig_scopes_len = self.scopes_len();
+        assert!(orig_scopes_len > 0);
+
+        // Remove any scopes that do not have cleanups on failure:
+        let mut popped_scopes = opt_vec::Empty;
+        while !self.top_scope(|s| s.needs_invoke()) {
+            debug!("top scope does not need invoke");
+            popped_scopes.push(self.pop_scope());
+        }
+
+        // Check for an existing landing pad in the new topmost scope:
+        let llbb = self.get_or_create_landing_pad();
+
+        // Push the scopes we removed back on:
+        while !popped_scopes.is_empty() {
+            self.push_scope(popped_scopes.pop());
+        }
+
+        assert_eq!(self.scopes_len(), orig_scopes_len);
+
+        return llbb;
+    }
+}
+
+impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
+    fn top_ast_scope(&self) -> Option<ast::NodeId> {
+        /*!
+         * Returns the id of the current top-most AST scope, if any.
+         */
+        let scopes = self.scopes.borrow();
+        for scope in scopes.get().iter().invert() {
+            match scope.kind {
+                CustomScopeKind | LoopScopeKind(..) => {}
+                AstScopeKind(i) => {
+                    return Some(i);
+                }
+            }
+        }
+        None
+    }
+
+    fn top_nonempty_cleanup_scope(&self) -> Option<uint> {
+        let scopes = self.scopes.borrow();
+        scopes.get().iter().invert().position(|s| !s.cleanups.is_empty())
+    }
+
+    fn is_valid_to_pop_custom_scope(&self, custom_scope: CustomScopeIndex) -> bool {
+        let scopes = self.scopes.borrow();
+        self.is_valid_custom_scope(custom_scope) &&
+            custom_scope.index == scopes.get().len() - 1
+    }
+
+    fn is_valid_custom_scope(&self, custom_scope: CustomScopeIndex) -> bool {
+        let scopes = self.scopes.borrow();
+        custom_scope.index < scopes.get().len() &&
+            scopes.get()[custom_scope.index].kind.is_temp()
+    }
+
+    fn trans_scope_cleanups(&self, // cannot borrow self, will recurse
+                            bcx: &'a Block<'a>,
+                            scope: &CleanupScope) -> &'a Block<'a> {
+        /*! Generates the cleanups for `scope` into `bcx` */
+
+        let mut bcx = bcx;
+        if !bcx.unreachable.get() {
+            for cleanup in scope.cleanups.iter().invert() {
+                bcx = cleanup.trans(bcx);
+            }
+        }
+        bcx
+    }
+
+    fn scopes_len(&self) -> uint {
+        let scopes = self.scopes.borrow();
+        scopes.get().len()
+    }
+
+    fn push_scope(&self, scope: CleanupScope<'a>) {
+        let mut scopes = self.scopes.borrow_mut();
+        scopes.get().push(scope);
+    }
+
+    fn pop_scope(&self) -> CleanupScope<'a> {
+        debug!("popping cleanup scope {}, {} scopes remaining",
+               self.top_scope(|s| s.block_name("")),
+               self.scopes_len() - 1);
+
+        let mut scopes = self.scopes.borrow_mut();
+        scopes.get().pop()
+    }
+
+    fn top_scope<R>(&self, f: |&CleanupScope<'a>| -> R) -> R {
+        let scopes = self.scopes.borrow();
+        f(scopes.get().last())
+    }
+
+    fn trans_cleanups_to_exit_scope(&self,
+                                    label: EarlyExitLabel)
+                                    -> BasicBlockRef {
+        /*!
+         * Used when the caller wishes to jump to an early exit, such
+         * as a return, break, continue, or unwind. This function will
+         * generate all cleanups between the top of the stack and the
+         * exit `label` and return a basic block that the caller can
+         * branch to.
+         *
+         * For example, if the current stack of cleanups were as follows:
+         *
+         *      AST 22
+         *      Custom 1
+         *      AST 23
+         *      Loop 23
+         *      Custom 2
+         *      AST 24
+         *
+         * and the `label` specifies a break from `Loop 23`, then this
+         * function would generate a series of basic blocks as follows:
+         *
+         *      Cleanup(AST 24) -> Cleanup(Custom 2) -> break_blk
+         *
+         * where `break_blk` is the block specified in `Loop 23` as
+         * the target for breaks. The return value would be the first
+         * basic block in that sequence (`Cleanup(AST 24)`). The
+         * caller could then branch to `Cleanup(AST 24)` and it will
+         * perform all cleanups and finally branch to the `break_blk`.
+         */
+
+        debug!("trans_cleanups_to_exit_scope label={:?} scopes={}",
+               label, self.scopes_len());
+
+        let orig_scopes_len = self.scopes_len();
+        let mut prev_llbb;
+        let mut popped_scopes = opt_vec::Empty;
+
+        // First we pop off all the cleanup stacks that are
+        // traversed until the exit is reached, pushing them
+        // onto the side vector `popped_scopes`. No code is
+        // generated at this time.
+        //
+        // So, continuing the example from above, we would wind up
+        // with a `popped_scopes` vector of `[AST 24, Custom 2]`.
+        // (Presuming that there are no cached exits)
+        loop {
+            if self.scopes_len() == 0 {
+                match label {
+                    UnwindExit => {
+                        // Generate a block that will `Resume`.
+                        let prev_bcx = self.new_block(true, "resume", None);
+                        let personality = self.personality.get().expect(
+                            "create_landing_pad() should have set this");
+                        build::Resume(prev_bcx,
+                                      build::Load(prev_bcx, personality));
+                        prev_llbb = prev_bcx.llbb;
+                        break;
+                    }
+
+                    ReturnExit => {
+                        prev_llbb = self.get_llreturn();
+                        break;
+                    }
+
+                    LoopExit(id, _) => {
+                        self.ccx.tcx.sess.bug(format!(
+                                "Cannot exit from scope {:?}, \
+                                not in scope", id));
+                    }
+                }
+            }
+
+            // Check if we have already cached the unwinding of this
+            // scope for this label. If so, we can stop popping scopes
+            // and branch to the cached label, since it contains the
+            // cleanups for any subsequent scopes.
+            match self.top_scope(|s| s.cached_early_exit(label)) {
+                Some(cleanup_block) => {
+                    prev_llbb = cleanup_block;
+                    break;
+                }
+                None => { }
+            }
+
+            // Pop off the scope, since we will be generating
+            // unwinding code for it. If we are searching for a loop exit,
+            // and this scope is that loop, then stop popping and set
+            // `prev_llbb` to the appropriate exit block from the loop.
+            popped_scopes.push(self.pop_scope());
+            let scope = popped_scopes.last();
+            match label {
+                UnwindExit | ReturnExit => { }
+                LoopExit(id, exit) => {
+                    match scope.kind.early_exit_block(id, exit) {
+                        Some(exitllbb) => {
+                            prev_llbb = exitllbb;
+                            break;
+                        }
+
+                        None => { }
+                    }
+                }
+            }
+        }
+
+        debug!("trans_cleanups_to_exit_scope: popped {} scopes",
+               popped_scopes.len());
+
+        // Now push the popped scopes back on. As we go,
+        // we track in `prev_llbb` the exit to which this scope
+        // should branch when it's done.
+        //
+        // So, continuing with our example, we will start out with
+        // `prev_llbb` being set to `break_blk` (or possibly a cached
+        // early exit). We will then pop the scopes from `popped_scopes`
+        // and generate a basic block for each one, prepending it in the
+        // series and updating `prev_llbb`. So we begin by popping `Custom 2`
+        // and generating `Cleanup(Custom 2)`. We make `Cleanup(Custom 2)`
+        // branch to `prev_llbb == break_blk`, giving us a sequence like:
+        //
+        //     Cleanup(Custom 2) -> prev_llbb
+        //
+        // We then pop `AST 24` and repeat the process, giving us the sequence:
+        //
+        //     Cleanup(AST 24) -> Cleanup(Custom 2) -> prev_llbb
+        //
+        // At this point, `popped_scopes` is empty, and so the final block
+        // that we return to the user is `Cleanup(AST 24)`.
+        while !popped_scopes.is_empty() {
+            let mut scope = popped_scopes.pop();
+
+            if scope.cleanups.iter().any(|c| cleanup_is_suitable_for(*c, label))
+            {
+                let name = scope.block_name("clean");
+                debug!("generating cleanups for {}", name);
+                let bcx_in = self.new_block(label.is_unwind(), name, None);
+                let mut bcx_out = bcx_in;
+                for cleanup in scope.cleanups.iter().invert() {
+                    if cleanup_is_suitable_for(*cleanup, label) {
+                        bcx_out = cleanup.trans(bcx_out);
+                    }
+                }
+                build::Br(bcx_out, prev_llbb);
+                prev_llbb = bcx_in.llbb;
+            } else {
+                debug!("no suitable cleanups in {}",
+                       scope.block_name("clean"));
+            }
+
+            scope.add_cached_early_exit(label, prev_llbb);
+            self.push_scope(scope);
+        }
+
+        debug!("trans_cleanups_to_exit_scope: prev_llbb={}", prev_llbb);
+
+        assert_eq!(self.scopes_len(), orig_scopes_len);
+        prev_llbb
+    }
+
+    fn get_or_create_landing_pad(&self) -> BasicBlockRef {
+        /*!
+         * Creates a landing pad for the top scope, if one does not
+         * exist.  The landing pad will perform all cleanups necessary
+         * for an unwind and then `resume` to continue error
+         * propagation:
+         *
+         *     landing_pad -> ... cleanups ... -> [resume]
+         *
+         * (The cleanups and resume instruction are created by
+         * `trans_cleanups_to_exit_scope()`, not in this function
+         * itself.)
+         */
+
+        let pad_bcx;
+
+        debug!("get_or_create_landing_pad");
+
+        // Check if a landing pad block exists; if not, create one.
+        {
+            let mut scopes = self.scopes.borrow_mut();
+            let last_scope = scopes.get().mut_last();
+            match last_scope.cached_landing_pad {
+                Some(llbb) => { return llbb; }
+                None => {
+                    let name = last_scope.block_name("unwind");
+                    pad_bcx = self.new_block(true, name, None);
+                    last_scope.cached_landing_pad = Some(pad_bcx.llbb);
+                }
+            }
+        }
+
+        // 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_([Type::i8p(), Type::i32()], false);
+
+        // The exception handling personality function.
+        let def_id = common::langcall(pad_bcx, None, "", EhPersonalityLangItem);
+        let llpersonality = callee::trans_fn_ref(pad_bcx, def_id, 0).llfn;
+
+        // The only landing pad clause will be 'cleanup'
+        let llretval = build::LandingPad(pad_bcx, llretty, llpersonality, 1u);
+
+        // The landing pad block is a cleanup
+        build::SetCleanup(pad_bcx, llretval);
+
+        // We store the retval in a function-central alloca, so that calls to
+        // Resume can find it.
+        match self.personality.get() {
+            Some(addr) => {
+                build::Store(pad_bcx, llretval, addr);
+            }
+            None => {
+                let addr = base::alloca(pad_bcx, common::val_ty(llretval), "");
+                self.personality.set(Some(addr));
+                build::Store(pad_bcx, llretval, addr);
+            }
+        }
+
+        // Generate the cleanup block and branch to it.
+        let cleanup_llbb = self.trans_cleanups_to_exit_scope(UnwindExit);
+        build::Br(pad_bcx, cleanup_llbb);
+
+        return pad_bcx.llbb;
+    }
+}
+
+impl<'a> CleanupScope<'a> {
+    fn new(kind: CleanupScopeKind<'a>) -> CleanupScope<'a> {
+        CleanupScope {
+            kind: kind,
+            cleanups: opt_vec::Empty,
+            cached_early_exits: opt_vec::Empty,
+            cached_landing_pad: None,
+        }
+    }
+
+    fn clear_cached_exits(&mut self) {
+        self.cached_early_exits = opt_vec::Empty;
+        self.cached_landing_pad = None;
+    }
+
+    fn cached_early_exit(&self,
+                         label: EarlyExitLabel)
+                         -> Option<BasicBlockRef> {
+        self.cached_early_exits.iter().
+            find(|e| e.label == label).
+            map(|e| e.cleanup_block)
+    }
+
+    fn add_cached_early_exit(&mut self,
+                             label: EarlyExitLabel,
+                             blk: BasicBlockRef) {
+        self.cached_early_exits.push(
+            CachedEarlyExit { label: label,
+                              cleanup_block: blk });
+    }
+
+    fn needs_invoke(&self) -> bool {
+        /*! True if this scope has cleanups for use during unwinding */
+
+        self.cached_landing_pad.is_some() ||
+            self.cleanups.iter().any(|c| c.clean_on_unwind())
+    }
+
+    fn block_name(&self, prefix: &str) -> ~str {
+        /*!
+         * Returns a suitable name to use for the basic block that
+         * handles this cleanup scope
+         */
+
+        match self.kind {
+            CustomScopeKind => format!("{}_custom_", prefix),
+            AstScopeKind(id) => format!("{}_ast_{}_", prefix, id),
+            LoopScopeKind(id, _) => format!("{}_loop_{}_", prefix, id),
+        }
+    }
+}
+
+impl<'a> CleanupScopeKind<'a> {
+    fn is_temp(&self) -> bool {
+        match *self {
+            CustomScopeKind => true,
+            LoopScopeKind(..) | AstScopeKind(..) => false,
+        }
+    }
+
+    fn is_ast_with_id(&self, id: ast::NodeId) -> bool {
+        match *self {
+            CustomScopeKind | LoopScopeKind(..) => false,
+            AstScopeKind(i) => i == id
+        }
+    }
+
+    fn is_loop_with_id(&self, id: ast::NodeId) -> bool {
+        match *self {
+            CustomScopeKind | AstScopeKind(..) => false,
+            LoopScopeKind(i, _) => i == id
+        }
+    }
+
+    fn early_exit_block(&self,
+                        id: ast::NodeId,
+                        exit: uint) -> Option<BasicBlockRef> {
+        /*!
+         * If this is a loop scope with id `id`, return the early
+         * exit block `exit`, else `None`
+         */
+
+        match *self {
+            LoopScopeKind(i, ref exits) if id == i => Some(exits[exit].llbb),
+            _ => None,
+        }
+    }
+}
+
+impl EarlyExitLabel {
+    fn is_unwind(&self) -> bool {
+        match *self {
+            UnwindExit => true,
+            _ => false
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Cleanup types
+
+pub struct DropValue {
+    is_immediate: bool,
+    on_unwind: bool,
+    val: ValueRef,
+    ty: ty::t,
+}
+
+impl Cleanup for DropValue {
+    fn clean_on_unwind(&self) -> bool {
+        self.on_unwind
+    }
+
+    fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
+        if self.is_immediate {
+            glue::drop_ty_immediate(bcx, self.val, self.ty)
+        } else {
+            glue::drop_ty(bcx, self.val, self.ty)
+        }
+    }
+}
+
+pub struct FreeValue {
+    ptr: ValueRef,
+    heap: common::heap,
+}
+
+impl Cleanup for FreeValue {
+    fn clean_on_unwind(&self) -> bool {
+        true
+    }
+
+    fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
+        match self.heap {
+            common::heap_managed => {
+                glue::trans_free(bcx, self.ptr)
+            }
+            common::heap_exchange | common::heap_exchange_closure => {
+                glue::trans_exchange_free(bcx, self.ptr)
+            }
+        }
+    }
+}
+
+pub fn temporary_scope(tcx: ty::ctxt,
+                       id: ast::NodeId)
+                       -> ScopeId {
+    match tcx.region_maps.temporary_scope(id) {
+        Some(scope) => {
+            let r = AstScope(scope);
+            debug!("temporary_scope({}) = {:?}", id, r);
+            r
+        }
+        None => {
+            tcx.sess.bug(format!("no temporary scope available for expr {}", id))
+        }
+    }
+}
+
+pub fn var_scope(tcx: ty::ctxt,
+                 id: ast::NodeId)
+                 -> ScopeId {
+    let r = AstScope(tcx.region_maps.var_scope(id));
+    debug!("var_scope({}) = {:?}", id, r);
+    r
+}
+
+fn cleanup_is_suitable_for(c: &Cleanup,
+                           label: EarlyExitLabel) -> bool {
+    !label.is_unwind() || c.clean_on_unwind()
+}
+
+///////////////////////////////////////////////////////////////////////////
+// These traits just exist to put the methods into this file.
+
+pub trait CleanupMethods<'a> {
+    fn push_ast_cleanup_scope(&self, id: ast::NodeId);
+    fn push_loop_cleanup_scope(&self,
+                                   id: ast::NodeId,
+                                   exits: [&'a Block<'a>, ..EXIT_MAX]);
+    fn push_custom_cleanup_scope(&self) -> CustomScopeIndex;
+    fn pop_and_trans_ast_cleanup_scope(&self,
+                                              bcx: &'a Block<'a>,
+                                              cleanup_scope: ast::NodeId)
+                                              -> &'a Block<'a>;
+    fn pop_loop_cleanup_scope(&self,
+                              cleanup_scope: ast::NodeId);
+    fn pop_custom_cleanup_scope(&self,
+                                custom_scope: CustomScopeIndex);
+    fn pop_and_trans_custom_cleanup_scope(&self,
+                                          bcx: &'a Block<'a>,
+                                          custom_scope: CustomScopeIndex)
+                                          -> &'a Block<'a>;
+    fn top_loop_scope(&self) -> ast::NodeId;
+    fn normal_exit_block(&self,
+                         cleanup_scope: ast::NodeId,
+                         exit: uint) -> BasicBlockRef;
+    fn return_exit_block(&self) -> BasicBlockRef;
+    fn schedule_drop_mem(&self,
+                         cleanup_scope: ScopeId,
+                         val: ValueRef,
+                         ty: ty::t);
+    fn schedule_drop_immediate(&self,
+                               cleanup_scope: ScopeId,
+                               val: ValueRef,
+                               ty: ty::t);
+    fn schedule_free_value(&self,
+                           cleanup_scope: ScopeId,
+                           val: ValueRef,
+                           heap: common::heap);
+    fn schedule_clean(&self,
+                      cleanup_scope: ScopeId,
+                      cleanup: ~Cleanup);
+    fn schedule_clean_in_ast_scope(&self,
+                                   cleanup_scope: ast::NodeId,
+                                   cleanup: ~Cleanup);
+    fn schedule_clean_in_custom_scope(&self,
+                                    custom_scope: CustomScopeIndex,
+                                    cleanup: ~Cleanup);
+    fn needs_invoke(&self) -> bool;
+    fn get_landing_pad(&self) -> BasicBlockRef;
+}
+
+trait CleanupHelperMethods<'a> {
+    fn top_ast_scope(&self) -> Option<ast::NodeId>;
+    fn top_nonempty_cleanup_scope(&self) -> Option<uint>;
+    fn is_valid_to_pop_custom_scope(&self, custom_scope: CustomScopeIndex) -> bool;
+    fn is_valid_custom_scope(&self, custom_scope: CustomScopeIndex) -> bool;
+    fn trans_scope_cleanups(&self,
+                            bcx: &'a Block<'a>,
+                            scope: &CleanupScope<'a>) -> &'a Block<'a>;
+    fn trans_cleanups_to_exit_scope(&self,
+                                    label: EarlyExitLabel)
+                                    -> BasicBlockRef;
+    fn get_or_create_landing_pad(&self) -> BasicBlockRef;
+    fn scopes_len(&self) -> uint;
+    fn push_scope(&self, scope: CleanupScope<'a>);
+    fn pop_scope(&self) -> CleanupScope<'a>;
+    fn top_scope<R>(&self, f: |&CleanupScope<'a>| -> R) -> R;
+}
index 25bc968b987dc6146a4294e2a3b0ddc8c7e61089..58f7171452e7df6178419d3cb026d73dd908a917 100644 (file)
@@ -16,7 +16,7 @@
 use middle::trans::base::*;
 use middle::trans::build::*;
 use middle::trans::common::*;
-use middle::trans::datum::{Datum, INIT};
+use middle::trans::datum::{Datum, Lvalue};
 use middle::trans::debuginfo;
 use middle::trans::expr;
 use middle::trans::glue;
@@ -112,7 +112,7 @@ pub enum EnvAction {
 
 pub struct EnvValue {
     action: EnvAction,
-    datum: Datum
+    datum: Datum<Lvalue>
 }
 
 impl EnvAction {
@@ -131,11 +131,6 @@ pub fn to_str(&self, ccx: &CrateContext) -> ~str {
     }
 }
 
-pub fn mk_tuplified_uniq_cbox_ty(tcx: ty::ctxt, cdata_ty: ty::t) -> ty::t {
-    let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
-    return ty::mk_imm_uniq(tcx, cbox_ty);
-}
-
 // Given a closure ty, emits a corresponding tuple ty
 pub fn mk_closure_tys(tcx: ty::ctxt,
                       bound_values: &[EnvValue])
@@ -155,14 +150,6 @@ pub fn mk_closure_tys(tcx: ty::ctxt,
     return cdata_ty;
 }
 
-fn heap_for_unique_closure(bcx: &Block, t: ty::t) -> heap {
-    if ty::type_contents(bcx.tcx(), t).owns_managed() {
-        heap_managed_unique
-    } else {
-        heap_exchange_closure
-    }
-}
-
 pub fn allocate_cbox<'a>(
                      bcx: &'a Block<'a>,
                      sigil: ast::Sigil,
@@ -178,7 +165,7 @@ pub fn allocate_cbox<'a>(
             tcx.sess.bug("trying to trans allocation of @fn")
         }
         ast::OwnedSigil => {
-            malloc_raw(bcx, cdata_ty, heap_for_unique_closure(bcx, cdata_ty))
+            malloc_raw(bcx, cdata_ty, heap_exchange_closure)
         }
         ast::BorrowedSigil => {
             let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
@@ -232,7 +219,7 @@ pub fn store_environment<'a>(
 
     // Copy expr values into boxed bindings.
     let mut bcx = bcx;
-    for (i, bv) in bound_values.iter().enumerate() {
+    for (i, bv) in bound_values.move_iter().enumerate() {
         debug!("Copy {} into closure", bv.to_str(ccx));
 
         if ccx.sess.asm_comments() {
@@ -243,17 +230,13 @@ pub fn store_environment<'a>(
         let bound_data = GEPi(bcx, llbox, [0u, abi::box_field_body, i]);
 
         match bv.action {
-            EnvCopy => {
-                bcx = bv.datum.copy_to(bcx, INIT, bound_data);
-            }
-            EnvMove => {
-                bcx = bv.datum.move_to(bcx, INIT, bound_data);
+            EnvCopy | EnvMove => {
+                bcx = bv.datum.store_to(bcx, bound_data);
             }
             EnvRef => {
-                Store(bcx, bv.datum.to_ref_llval(bcx), bound_data);
+                Store(bcx, bv.datum.to_llref(), bound_data);
             }
         }
-
     }
 
     ClosureResult { llbox: llbox, cdata_ty: cdata_ty, bcx: bcx }
@@ -426,7 +409,6 @@ pub fn trans_expr_fn<'a>(
                           None,
                           bcx.fcx.param_substs,
                           user_id,
-                          None,
                           [],
                           ty::ty_fn_ret(fty),
                           |fcx| load_environment(fcx, cdata_ty, cap_vars, sigil));
index 7f6ab2dd9d154a6bb808fcdaeffba30b72112bd9..e466e4da38d72f779eb5c0f00c681d8dde0667fa 100644 (file)
@@ -20,8 +20,9 @@
 use middle::lang_items::LangItem;
 use middle::trans::base;
 use middle::trans::build;
+use middle::trans::cleanup;
 use middle::trans::datum;
-use middle::trans::glue;
+use middle::trans::datum::{Datum, Lvalue};
 use middle::trans::debuginfo;
 use middle::trans::type_::Type;
 use middle::ty::substs;
@@ -37,8 +38,7 @@
 use std::cell::{Cell, RefCell};
 use std::hashmap::HashMap;
 use std::libc::{c_uint, c_longlong, c_ulonglong, c_char};
-use std::vec;
-use syntax::ast::{Name, Ident};
+use syntax::ast::{Ident};
 use syntax::ast_map::{Path, PathElem, PathPrettyName};
 use syntax::codemap::Span;
 use syntax::parse::token;
@@ -64,7 +64,7 @@ pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
     let tcx = ccx.tcx;
     let simple = ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
         ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
-        type_is_newtype_immediate(ccx, ty) ||
+        type_is_newtype_immediate(ccx, ty) || ty::type_is_bot(ty) ||
         ty::type_is_simd(tcx, ty);
     if simple {
         return true;
@@ -75,10 +75,33 @@ pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
             let llty = sizing_type_of(ccx, ty);
             llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type)
         }
-        _ => false
+        _ => type_is_zero_size(ccx, ty)
     }
 }
 
+pub fn type_is_zero_size(ccx: &CrateContext, ty: ty::t) -> bool {
+    /*!
+     * Identify types which have size zero at runtime.
+     */
+
+    use middle::trans::machine::llsize_of_alloc;
+    use middle::trans::type_of::sizing_type_of;
+    let llty = sizing_type_of(ccx, ty);
+    llsize_of_alloc(ccx, llty) == 0
+}
+
+pub fn return_type_is_void(ccx: &CrateContext, ty: ty::t) -> bool {
+    /*!
+     * Identifies types which we declare to be equivalent to `void`
+     * in C for the purpose of function return types. These are
+     * `()`, bot, and uninhabited enums. Note that all such types
+     * are also zero-size, but not all zero-size types use a `void`
+     * return type (in order to aid with C ABI compatibility).
+     */
+
+    ty::type_is_nil(ty) || ty::type_is_bot(ty) || ty::type_is_empty(ccx.tcx, ty)
+}
+
 pub fn gensym_name(name: &str) -> (Ident, PathElem) {
     let name = token::gensym(name);
     let ident = Ident::new(name);
@@ -90,7 +113,6 @@ pub struct tydesc_info {
     tydesc: ValueRef,
     size: ValueRef,
     align: ValueRef,
-    borrow_offset: ValueRef,
     name: ValueRef,
     take_glue: Cell<Option<ValueRef>>,
     drop_glue: Cell<Option<ValueRef>>,
@@ -123,6 +145,15 @@ pub struct tydesc_info {
  *
  */
 
+pub struct NodeInfo {
+    id: ast::NodeId,
+    span: Span,
+}
+
+pub fn expr_info(expr: &ast::Expr) -> NodeInfo {
+    NodeInfo { id: expr.id, span: expr.span }
+}
+
 pub struct Stats {
     n_static_tydescs: Cell<uint>,
     n_glues_created: Cell<uint>,
@@ -186,6 +217,10 @@ fn repr(&self, tcx: ty::ctxt) -> ~str {
     }
 }
 
+// work around bizarre resolve errors
+type RvalueDatum = datum::Datum<datum::Rvalue>;
+type LvalueDatum = datum::Datum<datum::Lvalue>;
+
 // Function context.  Every LLVM function we create will have one of
 // these.
 pub struct FunctionContext<'a> {
@@ -214,13 +249,15 @@ pub struct FunctionContext<'a> {
     // allocas, so that LLVM will coalesce them into a single alloca call.
     alloca_insert_pt: Cell<Option<ValueRef>>,
     llreturn: Cell<Option<BasicBlockRef>>,
+
     // The 'self' value currently in use in this function, if there
     // is one.
     //
     // NB: This is the type of the self *variable*, not the self *type*. The
     // self type is set only for default methods, while the self variable is
     // set for all methods.
-    llself: Cell<Option<datum::Datum>>,
+    llself: Cell<Option<LvalueDatum>>,
+
     // The a value alloca'd for calls to upcalls.rust_personality. Used when
     // outputting the resume instruction.
     personality: Cell<Option<ValueRef>>,
@@ -231,10 +268,12 @@ pub struct FunctionContext<'a> {
     caller_expects_out_pointer: bool,
 
     // Maps arguments to allocas created for them in llallocas.
-    llargs: RefCell<HashMap<ast::NodeId, datum::Datum>>,
+    llargs: RefCell<HashMap<ast::NodeId, LvalueDatum>>,
+
     // Maps the def_ids for local variables to the allocas created for
     // them in llallocas.
-    lllocals: RefCell<HashMap<ast::NodeId, datum::Datum>>,
+    lllocals: RefCell<HashMap<ast::NodeId, LvalueDatum>>,
+
     // Same as above, but for closure upvars
     llupvars: RefCell<HashMap<ast::NodeId, ValueRef>>,
 
@@ -254,14 +293,14 @@ pub struct FunctionContext<'a> {
     // The arena that blocks are allocated from.
     block_arena: TypedArena<Block<'a>>,
 
-    // The arena that scope info is allocated from.
-    scope_info_arena: TypedArena<ScopeInfo<'a>>,
-
     // This function's enclosing crate context.
     ccx: @CrateContext,
 
     // Used and maintained by the debuginfo module.
     debug_context: debuginfo::FunctionDebugContext,
+
+    // Cleanup scopes.
+    scopes: RefCell<~[cleanup::CleanupScope<'a>]>,
 }
 
 impl<'a> FunctionContext<'a> {
@@ -303,316 +342,67 @@ pub fn get_llreturn(&self) -> BasicBlockRef {
 
         self.llreturn.get().unwrap()
     }
-}
 
-pub fn warn_not_to_commit(ccx: &CrateContext, msg: &str) {
-    if !ccx.do_not_commit_warning_issued.get() {
-        ccx.do_not_commit_warning_issued.set(true);
-        ccx.sess.warn(msg.to_str() + " -- do not commit like this!");
-    }
-}
-
-// Heap selectors. Indicate which heap something should go on.
-#[deriving(Eq)]
-pub enum heap {
-    heap_managed,
-    heap_managed_unique,
-    heap_exchange,
-    heap_exchange_closure
-}
-
-#[deriving(Clone, Eq)]
-pub enum cleantype {
-    normal_exit_only,
-    normal_exit_and_unwind
-}
-
-// Cleanup functions
-
-/// A cleanup function: a built-in destructor.
-pub trait CleanupFunction {
-    fn clean<'a>(&self, block: &'a Block<'a>) -> &'a Block<'a>;
-}
-
-/// A cleanup function that calls the "drop glue" (destructor function) on
-/// a datum.
-struct DatumDroppingCleanupFunction {
-    datum: datum::Datum
-}
-
-impl CleanupFunction for DatumDroppingCleanupFunction {
-    fn clean<'a>(&self, block: &'a Block<'a>) -> &'a Block<'a> {
-        self.datum.drop_val(block)
-    }
-}
-
-/// A cleanup function that frees some memory in the garbage-collected heap.
-pub struct GCHeapFreeingCleanupFunction {
-    ptr: ValueRef,
-}
-
-impl CleanupFunction for GCHeapFreeingCleanupFunction {
-    fn clean<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
-        glue::trans_free(bcx, self.ptr)
-    }
-}
-
-/// A cleanup function that frees some memory in the exchange heap.
-pub struct ExchangeHeapFreeingCleanupFunction {
-    ptr: ValueRef,
-}
-
-impl CleanupFunction for ExchangeHeapFreeingCleanupFunction {
-    fn clean<'a>(&self, bcx: &'a Block) -> &'a Block<'a> {
-        glue::trans_exchange_free(bcx, self.ptr)
-    }
-}
-
-pub enum cleanup {
-    Clean(@CleanupFunction, cleantype),
-    CleanTemp(ValueRef, @CleanupFunction, cleantype),
-}
-
-// Can't use deriving(Clone) because of the managed closure.
-impl Clone for cleanup {
-    fn clone(&self) -> cleanup {
-        match *self {
-            Clean(f, ct) => Clean(f, ct),
-            CleanTemp(v, f, ct) => CleanTemp(v, f, ct),
+    pub fn new_block(&'a self,
+                     is_lpad: bool,
+                     name: &str,
+                     opt_node_id: Option<ast::NodeId>)
+                     -> &'a Block<'a> {
+        unsafe {
+            let llbb = name.with_c_str(|buf| {
+                    llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx,
+                                                        self.llfn,
+                                                        buf)
+                });
+            Block::new(llbb, is_lpad, opt_node_id, self)
         }
     }
-}
 
-// Used to remember and reuse existing cleanup paths
-// target: none means the path ends in an resume instruction
-#[deriving(Clone)]
-pub struct cleanup_path {
-    target: Option<BasicBlockRef>,
-    size: uint,
-    dest: BasicBlockRef
-}
-
-pub fn shrink_scope_clean(scope_info: &ScopeInfo, size: uint) {
-    scope_info.landing_pad.set(None);
-    let new_cleanup_paths = {
-        let cleanup_paths = scope_info.cleanup_paths.borrow();
-        cleanup_paths.get()
-                     .iter()
-                     .take_while(|&cu| cu.size <= size)
-                     .map(|&x| x)
-                     .collect()
-    };
-    scope_info.cleanup_paths.set(new_cleanup_paths)
-}
-
-pub fn grow_scope_clean(scope_info: &ScopeInfo) {
-    scope_info.landing_pad.set(None);
-}
-
-pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
-    if ty::type_needs_unwind_cleanup(cx, ty) {
-        normal_exit_and_unwind
-    } else {
-        normal_exit_only
+    pub fn new_id_block(&'a self,
+                        name: &str,
+                        node_id: ast::NodeId)
+                        -> &'a Block<'a> {
+        self.new_block(false, name, Some(node_id))
     }
-}
-
-pub fn add_clean(bcx: &Block, val: ValueRef, ty: ty::t) {
-    if !ty::type_needs_drop(bcx.tcx(), ty) { return; }
-
-    debug!("add_clean({}, {}, {})", bcx.to_str(), bcx.val_to_str(val), ty.repr(bcx.tcx()));
 
-    let cleanup_type = cleanup_type(bcx.tcx(), ty);
-    in_scope_cx(bcx, None, |scope_info| {
-        {
-            let mut cleanups = scope_info.cleanups.borrow_mut();
-            cleanups.get().push(Clean(@DatumDroppingCleanupFunction {
-                datum: datum::Datum {
-                    val: val,
-                    ty: ty,
-                    mode: datum::ByRef(datum::ZeroMem)
-                }
-            } as @CleanupFunction,
-            cleanup_type));
-        }
-        grow_scope_clean(scope_info);
-    })
-}
-
-pub fn add_clean_temp_immediate(bcx: &Block, val: ValueRef, ty: ty::t) {
-    if !ty::type_needs_drop(bcx.tcx(), ty) { return; }
-
-    debug!("add_clean_temp_immediate({}, {}, {})",
-           bcx.to_str(), bcx.val_to_str(val),
-           ty.repr(bcx.tcx()));
-    let cleanup_type = cleanup_type(bcx.tcx(), ty);
-    in_scope_cx(bcx, None, |scope_info| {
-        {
-            let mut cleanups = scope_info.cleanups.borrow_mut();
-            cleanups.get().push(CleanTemp(val, @DatumDroppingCleanupFunction {
-                datum: datum::Datum {
-                    val: val,
-                    ty: ty,
-                    mode: datum::ByValue
-                }
-            } as @CleanupFunction,
-            cleanup_type));
-        }
-        grow_scope_clean(scope_info);
-    })
-}
-
-pub fn add_clean_temp_mem(bcx: &Block, val: ValueRef, t: ty::t) {
-    add_clean_temp_mem_in_scope_(bcx, None, val, t);
-}
-
-pub fn add_clean_temp_mem_in_scope(bcx: &Block,
-                                   scope_id: ast::NodeId,
-                                   val: ValueRef,
-                                   t: ty::t) {
-    add_clean_temp_mem_in_scope_(bcx, Some(scope_id), val, t);
-}
-
-pub fn add_clean_temp_mem_in_scope_(bcx: &Block, scope_id: Option<ast::NodeId>,
-                                    val: ValueRef, t: ty::t) {
-    if !ty::type_needs_drop(bcx.tcx(), t) { return; }
-    debug!("add_clean_temp_mem({}, {}, {})",
-           bcx.to_str(), bcx.val_to_str(val),
-           t.repr(bcx.tcx()));
-    let cleanup_type = cleanup_type(bcx.tcx(), t);
-    in_scope_cx(bcx, scope_id, |scope_info| {
-        {
-            let mut cleanups = scope_info.cleanups.borrow_mut();
-            cleanups.get().push(CleanTemp(val, @DatumDroppingCleanupFunction {
-                datum: datum::Datum {
-                    val: val,
-                    ty: t,
-                    mode: datum::ByRef(datum::RevokeClean)
-                }
-            } as @CleanupFunction,
-            cleanup_type));
-        }
-        grow_scope_clean(scope_info);
-    })
-}
+    pub fn new_temp_block(&'a self,
+                          name: &str)
+                          -> &'a Block<'a> {
+        self.new_block(false, name, None)
+    }
 
-pub fn add_clean_free(cx: &Block, ptr: ValueRef, heap: heap) {
-    let free_fn = match heap {
-        heap_managed | heap_managed_unique => {
-            @GCHeapFreeingCleanupFunction {
-                ptr: ptr,
-            } as @CleanupFunction
+    pub fn join_blocks(&'a self,
+                       id: ast::NodeId,
+                       in_cxs: &[&'a Block<'a>])
+                       -> &'a Block<'a> {
+        let out = self.new_id_block("join", id);
+        let mut reachable = false;
+        for bcx in in_cxs.iter() {
+            if !bcx.unreachable.get() {
+                build::Br(*bcx, out.llbb);
+                reachable = true;
+            }
         }
-        heap_exchange | heap_exchange_closure => {
-            @ExchangeHeapFreeingCleanupFunction {
-                ptr: ptr,
-            } as @CleanupFunction
+        if !reachable {
+            build::Unreachable(out);
         }
-    };
-    in_scope_cx(cx, None, |scope_info| {
-        {
-            let mut cleanups = scope_info.cleanups.borrow_mut();
-            cleanups.get().push(CleanTemp(ptr,
-                                           free_fn,
-                                           normal_exit_and_unwind));
-        }
-        grow_scope_clean(scope_info);
-    })
-}
-
-// Note that this only works for temporaries. We should, at some point, move
-// to a system where we can also cancel the cleanup on local variables, but
-// this will be more involved. For now, we simply zero out the local, and the
-// drop glue checks whether it is zero.
-pub fn revoke_clean(cx: &Block, val: ValueRef) {
-    in_scope_cx(cx, None, |scope_info| {
-        let cleanup_pos = {
-            let mut cleanups = scope_info.cleanups.borrow_mut();
-            debug!("revoke_clean({}, {}) revoking {:?} from {:?}",
-                   cx.to_str(), cx.val_to_str(val), val, cleanups.get());
-            cleanups.get().iter().position(|cu| {
-                match *cu {
-                    CleanTemp(v, _, _) if v == val => true,
-                    _ => false
-                }
-            })
-        };
-        debug!("revoke_clean({}, {}) revoking {:?}",
-               cx.to_str(), cx.val_to_str(val), cleanup_pos);
-        for &i in cleanup_pos.iter() {
-            let new_cleanups = {
-                let cleanups = scope_info.cleanups.borrow();
-                vec::append(cleanups.get().slice(0u, i).to_owned(),
-                            cleanups.get().slice(i + 1u, cleanups.get()
-                                                                 .len()))
-            };
-            scope_info.cleanups.set(new_cleanups);
-            shrink_scope_clean(scope_info, i);
-        }
-    })
-}
-
-pub fn block_cleanups(bcx: &Block) -> ~[cleanup] {
-    match bcx.scope.get() {
-       None  => ~[],
-       Some(inf) => inf.cleanups.get(),
-    }
-}
-
-pub struct ScopeInfo<'a> {
-    parent: Option<&'a ScopeInfo<'a>>,
-    loop_break: Option<&'a Block<'a>>,
-    loop_label: Option<Name>,
-    // A list of functions that must be run at when leaving this
-    // block, cleaning up any variables that were introduced in the
-    // block.
-    cleanups: RefCell<~[cleanup]>,
-    // Existing cleanup paths that may be reused, indexed by destination and
-    // cleared when the set of cleanups changes.
-    cleanup_paths: RefCell<~[cleanup_path]>,
-    // Unwinding landing pad. Also cleared when cleanups change.
-    landing_pad: Cell<Option<BasicBlockRef>>,
-    // info about the AST node this scope originated from, if any
-    node_info: Option<NodeInfo>,
-}
-
-impl<'a> ScopeInfo<'a> {
-    pub fn empty_cleanups(&self) -> bool {
-        let cleanups = self.cleanups.borrow();
-        cleanups.get().is_empty()
-    }
-}
-
-pub trait get_node_info {
-    fn info(&self) -> Option<NodeInfo>;
-}
-
-impl get_node_info for ast::Expr {
-    fn info(&self) -> Option<NodeInfo> {
-        Some(NodeInfo {id: self.id,
-                       callee_id: self.get_callee_id(),
-                       span: self.span})
+        return out;
     }
 }
 
-impl get_node_info for ast::Block {
-    fn info(&self) -> Option<NodeInfo> {
-        Some(NodeInfo {id: self.id,
-                       callee_id: None,
-                       span: self.span})
-    }
-}
-
-impl get_node_info for Option<@ast::Expr> {
-    fn info(&self) -> Option<NodeInfo> {
-        self.as_ref().and_then(|s| s.info())
+pub fn warn_not_to_commit(ccx: &mut CrateContext, msg: &str) {
+    if !ccx.do_not_commit_warning_issued.get() {
+        ccx.do_not_commit_warning_issued.set(true);
+        ccx.sess.warn(msg.to_str() + " -- do not commit like this!");
     }
 }
 
-pub struct NodeInfo {
-    id: ast::NodeId,
-    callee_id: Option<ast::NodeId>,
-    span: Span
+// Heap selectors. Indicate which heap something should go on.
+#[deriving(Eq)]
+pub enum heap {
+    heap_managed,
+    heap_exchange,
+    heap_exchange_closure
 }
 
 // Basic block context.  We create a block context for each basic block
@@ -629,13 +419,14 @@ pub struct Block<'a> {
     llbb: BasicBlockRef,
     terminated: Cell<bool>,
     unreachable: Cell<bool>,
-    parent: Option<&'a Block<'a>>,
-    // The current scope within this basic block
-    scope: RefCell<Option<&'a ScopeInfo<'a>>>,
+
     // Is this block part of a landing pad?
     is_lpad: bool,
-    // info about the AST node this block originated from, if any
-    node_info: Option<NodeInfo>,
+
+    // AST node-id associated with this block, if any. Used for
+    // debugging purposes only.
+    opt_node_id: Option<ast::NodeId>,
+
     // The function context for the function to which this block is
     // attached.
     fcx: &'a FunctionContext<'a>,
@@ -644,20 +435,17 @@ pub struct Block<'a> {
 impl<'a> Block<'a> {
     pub fn new<'a>(
                llbb: BasicBlockRef,
-               parent: Option<&'a Block<'a>>,
                is_lpad: bool,
-               node_info: Option<NodeInfo>,
+               opt_node_id: Option<ast::NodeId>,
                fcx: &'a FunctionContext<'a>)
                -> &'a Block<'a> {
         fcx.block_arena.alloc(Block {
             llbb: llbb,
             terminated: Cell::new(false),
             unreachable: Cell::new(false),
-            parent: parent,
-            scope: RefCell::new(None),
             is_lpad: is_lpad,
-            node_info: node_info,
-            fcx: fcx,
+            opt_node_id: opt_node_id,
+            fcx: fcx
         })
     }
 
@@ -711,12 +499,8 @@ pub fn ty_to_str(&self, t: ty::t) -> ~str {
     }
 
     pub fn to_str(&self) -> ~str {
-        unsafe {
-            match self.node_info {
-                Some(node_info) => format!("[block {}]", node_info.id),
-                None => format!("[block {}]", transmute::<&Block, *Block>(self)),
-            }
-        }
+        let blk: *Block = self;
+        format!("[block {}]", blk)
     }
 }
 
@@ -745,48 +529,6 @@ pub fn val_ty(v: ValueRef) -> Type {
     }
 }
 
-pub fn in_scope_cx<'a>(
-                   cx: &'a Block<'a>,
-                   scope_id: Option<ast::NodeId>,
-                   f: |si: &'a ScopeInfo<'a>|) {
-    let mut cur = cx;
-    let mut cur_scope = cur.scope.get();
-    loop {
-        cur_scope = match cur_scope {
-            Some(inf) => match scope_id {
-                Some(wanted) => match inf.node_info {
-                    Some(NodeInfo { id: actual, .. }) if wanted == actual => {
-                        debug!("in_scope_cx: selected cur={} (cx={}) info={:?}",
-                               cur.to_str(), cx.to_str(), inf.node_info);
-                        f(inf);
-                        return;
-                    },
-                    _ => inf.parent,
-                },
-                None => {
-                    debug!("in_scope_cx: selected cur={} (cx={}) info={:?}",
-                           cur.to_str(), cx.to_str(), inf.node_info);
-                    f(inf);
-                    return;
-                }
-            },
-            None => {
-                cur = block_parent(cur);
-                cur.scope.get()
-            }
-        }
-    }
-}
-
-pub fn block_parent<'a>(cx: &'a Block<'a>) -> &'a Block<'a> {
-    match cx.parent {
-      Some(b) => b,
-      None    => cx.sess().bug(format!("block_parent called on root block {:?}",
-                                   cx))
-    }
-}
-
-
 // Let T be the content of a box @T.  tuplify_box_ty(t) returns the
 // representation of @T as a tuple (i.e., the ty::t version of what T_box()
 // returns).
@@ -1014,7 +756,7 @@ pub enum mono_param_id {
     mono_repr(uint /* size */,
               uint /* align */,
               MonoDataClass,
-              datum::DatumMode),
+              datum::RvalueMode),
 }
 
 #[deriving(Eq,IterBytes)]
index 97e338eab856573f392f5fb63cfa813565f3f899..ec47dbacb39c0eb85ebaa91fa16b2ea46f7b5b2c 100644 (file)
 use middle::trans::callee;
 use middle::trans::common::*;
 use middle::trans::debuginfo;
+use middle::trans::cleanup;
+use middle::trans::cleanup::CleanupMethods;
 use middle::trans::expr;
 use middle::ty;
-use util::common::indenter;
 use util::ppaux;
+use util::ppaux::Repr;
 
 use middle::trans::type_::Type;
 
 use syntax::codemap::Span;
 use syntax::visit::Visitor;
 
-pub fn trans_block<'a>(bcx: &'a Block<'a>, b: &ast::Block, dest: expr::Dest)
-                   -> &'a Block<'a> {
+pub fn trans_stmt<'a>(cx: &'a Block<'a>,
+                      s: &ast::Stmt)
+                      -> &'a Block<'a> {
+    let _icx = push_ctxt("trans_stmt");
+    let fcx = cx.fcx;
+    debug!("trans_stmt({})", s.repr(cx.tcx()));
+
+    if cx.sess().asm_comments() {
+        add_span_comment(cx, s.span, s.repr(cx.tcx()));
+    }
+
+    let mut bcx = cx;
+
+    let id = ast_util::stmt_id(s);
+    fcx.push_ast_cleanup_scope(id);
+
+    match s.node {
+        ast::StmtExpr(e, _) | ast::StmtSemi(e, _) => {
+            bcx = expr::trans_into(cx, e, expr::Ignore);
+        }
+        ast::StmtDecl(d, _) => {
+            match d.node {
+                ast::DeclLocal(ref local) => {
+                    bcx = init_local(bcx, *local);
+                    if cx.sess().opts.extra_debuginfo {
+                        debuginfo::create_local_var_metadata(bcx, *local);
+                    }
+                }
+                ast::DeclItem(i) => trans_item(cx.fcx.ccx, i)
+            }
+        }
+        ast::StmtMac(..) => cx.tcx().sess.bug("unexpanded macro")
+    }
+
+    bcx = fcx.pop_and_trans_ast_cleanup_scope(
+        bcx, ast_util::stmt_id(s));
+
+    return bcx;
+}
+
+pub fn trans_block<'a>(bcx: &'a Block<'a>,
+                       b: &ast::Block,
+                       dest: expr::Dest)
+                       -> &'a Block<'a> {
     let _icx = push_ctxt("trans_block");
+    let fcx = bcx.fcx;
     let mut bcx = bcx;
+
+    fcx.push_ast_cleanup_scope(b.id);
+
     for s in b.stmts.iter() {
         bcx = trans_stmt(bcx, *s);
     }
@@ -43,27 +91,26 @@ pub fn trans_block<'a>(bcx: &'a Block<'a>, b: &ast::Block, dest: expr::Dest)
             assert!(dest == expr::Ignore || bcx.unreachable.get());
         }
     }
+
+    bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, b.id);
+
     return bcx;
 }
 
-pub fn trans_if<'a>(
-                bcx: &'a Block<'a>,
-                cond: &ast::Expr,
-                thn: ast::P<ast::Block>,
-                els: Option<@ast::Expr>,
-                dest: expr::Dest)
-                -> &'a Block<'a> {
-    debug!("trans_if(bcx={}, cond={}, thn={:?}, dest={})",
-           bcx.to_str(), bcx.expr_to_str(cond), thn.id,
+pub fn trans_if<'a>(bcx: &'a Block<'a>,
+                    if_id: ast::NodeId,
+                    cond: &ast::Expr,
+                    thn: ast::P<ast::Block>,
+                    els: Option<@ast::Expr>,
+                    dest: expr::Dest)
+                    -> &'a Block<'a> {
+    debug!("trans_if(bcx={}, if_id={}, cond={}, thn={:?}, dest={})",
+           bcx.to_str(), if_id, bcx.expr_to_str(cond), thn.id,
            dest.to_str(bcx.ccx()));
-    let _indenter = indenter();
-
     let _icx = push_ctxt("trans_if");
+    let mut bcx = bcx;
 
-    let Result {bcx, val: cond_val} =
-        expr::trans_to_datum(bcx, cond).to_result();
-
-    let cond_val = bool_to_i1(bcx, cond_val);
+    let cond_val = unpack_result!(bcx, expr::trans(bcx, cond).to_llbool());
 
     // Drop branches that are known to be impossible
     if is_const(cond_val) && !is_undef(cond_val) {
@@ -76,11 +123,8 @@ pub fn trans_if<'a>(
                 None => {}
             }
             // if true { .. } [else { .. }]
-            return with_scope(bcx, thn.info(), "if_true_then", |bcx| {
-                let bcx_out = trans_block(bcx, thn, dest);
-                debuginfo::clear_source_location(bcx.fcx);
-                bcx_out
-            })
+            bcx = trans_block(bcx, thn, dest);
+            debuginfo::clear_source_location(bcx.fcx);
         } else {
             let mut trans = TransItemVisitor { ccx: bcx.fcx.ccx } ;
             trans.visit_block(thn, ());
@@ -88,229 +132,174 @@ pub fn trans_if<'a>(
             match els {
                 // if false { .. } else { .. }
                 Some(elexpr) => {
-                    return with_scope(bcx,
-                                      elexpr.info(),
-                                      "if_false_then",
-                                      |bcx| {
-                        let bcx_out = trans_if_else(bcx, elexpr, dest, false);
-                        debuginfo::clear_source_location(bcx.fcx);
-                        bcx_out
-                    })
+                    bcx = expr::trans_into(bcx, elexpr, dest);
+                    debuginfo::clear_source_location(bcx.fcx);
                 }
+
                 // if false { .. }
-                None => return bcx,
+                None => { }
             }
         }
-    }
 
-    let then_bcx_in = scope_block(bcx, thn.info(), "then");
+        return bcx;
+    }
 
+    let name = format!("then-block-{}-", thn.id);
+    let then_bcx_in = bcx.fcx.new_id_block(name, thn.id);
     let then_bcx_out = trans_block(then_bcx_in, thn, dest);
-
     debuginfo::clear_source_location(bcx.fcx);
-    let then_bcx_out = trans_block_cleanups(then_bcx_out,
-                                            block_cleanups(then_bcx_in));
-
-    // Calling trans_block directly instead of trans_expr
-    // because trans_expr will create another scope block
-    // context for the block, but we've already got the
-    // 'else' context
-    let (else_bcx_in, next_bcx) = match els {
-      Some(elexpr) => {
-          let else_bcx_in = scope_block(bcx, elexpr.info(), "else");
-          let else_bcx_out = trans_if_else(else_bcx_in, elexpr, dest, true);
-          (else_bcx_in, join_blocks(bcx, [then_bcx_out, else_bcx_out]))
-      }
-      _ => {
-          let next_bcx = sub_block(bcx, "next");
-          Br(then_bcx_out, next_bcx.llbb);
 
-          (next_bcx, next_bcx)
-      }
-    };
+    let next_bcx;
+    match els {
+        Some(elexpr) => {
+            let else_bcx_in = bcx.fcx.new_id_block("else-block", elexpr.id);
+            let else_bcx_out = expr::trans_into(else_bcx_in, elexpr, dest);
+            next_bcx = bcx.fcx.join_blocks(if_id,
+                                           [then_bcx_out, else_bcx_out]);
+            CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb);
+        }
 
-    debug!("then_bcx_in={}, else_bcx_in={}",
-           then_bcx_in.to_str(), else_bcx_in.to_str());
+        None => {
+            next_bcx = bcx.fcx.new_id_block("next-block", if_id);
+            Br(then_bcx_out, next_bcx.llbb);
+            CondBr(bcx, cond_val, then_bcx_in.llbb, next_bcx.llbb);
+        }
+    }
 
     // Clear the source location because it is still set to whatever has been translated
     // right before.
-    debuginfo::clear_source_location(else_bcx_in.fcx);
-    CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb);
-    return next_bcx;
-
-    // trans `else [ if { .. } ... | { .. } ]`
-    fn trans_if_else<'a>(
-                     else_bcx_in: &'a Block<'a>,
-                     elexpr: @ast::Expr,
-                     dest: expr::Dest,
-                     cleanup: bool)
-                     -> &'a Block<'a> {
-        let else_bcx_out = match elexpr.node {
-            ast::ExprIf(_, _, _) => {
-                let elseif_blk = ast_util::block_from_expr(elexpr);
-                trans_block(else_bcx_in, elseif_blk, dest)
-            }
-            ast::ExprBlock(blk) => {
-                trans_block(else_bcx_in, blk, dest)
-            }
-            // would be nice to have a constraint on ifs
-            _ => else_bcx_in.tcx().sess.bug("strange alternative in if")
-        };
-        if cleanup {
-            debuginfo::clear_source_location(else_bcx_in.fcx);
-            trans_block_cleanups(else_bcx_out, block_cleanups(else_bcx_in))
-        } else {
-            else_bcx_out
-        }
-    }
-}
+    debuginfo::clear_source_location(next_bcx.fcx);
 
-pub fn join_blocks<'a>(
-                   parent_bcx: &'a Block<'a>,
-                   in_cxs: &[&'a Block<'a>])
-                   -> &'a Block<'a> {
-    let out = sub_block(parent_bcx, "join");
-    let mut reachable = false;
-    for bcx in in_cxs.iter() {
-        if !bcx.unreachable.get() {
-            Br(*bcx, out.llbb);
-            reachable = true;
-        }
-    }
-    if !reachable {
-        Unreachable(out);
-    }
-    return out;
+    next_bcx
 }
 
-pub fn trans_while<'a>(
-                   bcx: &'a Block<'a>,
-                   cond: &ast::Expr,
-                   body: &ast::Block)
-                   -> &'a Block<'a> {
+pub fn trans_while<'a>(bcx: &'a Block<'a>,
+                       loop_id: ast::NodeId,
+                       cond: &ast::Expr,
+                       body: &ast::Block)
+                       -> &'a Block<'a> {
     let _icx = push_ctxt("trans_while");
-    let next_bcx = sub_block(bcx, "while next");
+    let fcx = bcx.fcx;
 
     //            bcx
     //             |
-    //          loop_bcx
-    //             |
     //         cond_bcx_in  <--------+
     //             |                 |
     //         cond_bcx_out          |
     //           |      |            |
     //           |    body_bcx_in    |
-    //    +------+      |            |
+    // cleanup_blk      |            |
     //    |           body_bcx_out --+
-    // next_bcx
+    // next_bcx_in
+
+    let next_bcx_in = fcx.new_id_block("while_exit", loop_id);
+    let cond_bcx_in = fcx.new_id_block("while_cond", cond.id);
+    let body_bcx_in = fcx.new_id_block("while_body", body.id);
+
+    fcx.push_loop_cleanup_scope(loop_id, [next_bcx_in, cond_bcx_in]);
 
-    let loop_bcx = loop_scope_block(bcx, next_bcx, None, "`while`",
-                                    body.info());
-    let cond_bcx_in = scope_block(loop_bcx, cond.info(), "while loop cond");
-    let body_bcx_in = scope_block(loop_bcx, body.info(), "while loop body");
-    Br(bcx, loop_bcx.llbb);
-    Br(loop_bcx, cond_bcx_in.llbb);
+    Br(bcx, cond_bcx_in.llbb);
+
+    // compile the block where we will handle loop cleanups
+    let cleanup_llbb = fcx.normal_exit_block(loop_id, cleanup::EXIT_BREAK);
 
     // compile the condition
     let Result {bcx: cond_bcx_out, val: cond_val} =
-        expr::trans_to_datum(cond_bcx_in, cond).to_result();
-    let cond_val = bool_to_i1(cond_bcx_out, cond_val);
-    let cond_bcx_out =
-        trans_block_cleanups(cond_bcx_out, block_cleanups(cond_bcx_in));
-    CondBr(cond_bcx_out, cond_val, body_bcx_in.llbb, next_bcx.llbb);
+        expr::trans(cond_bcx_in, cond).to_llbool();
+    CondBr(cond_bcx_out, cond_val, body_bcx_in.llbb, cleanup_llbb);
 
     // loop body:
     let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore);
-    cleanup_and_Br(body_bcx_out, body_bcx_in, cond_bcx_in.llbb);
+    Br(body_bcx_out, cond_bcx_in.llbb);
 
-    return next_bcx;
+    fcx.pop_loop_cleanup_scope(loop_id);
+    return next_bcx_in;
 }
 
-pub fn trans_loop<'a>(
-                  bcx: &'a Block<'a>,
-                  body: &ast::Block,
-                  opt_label: Option<Name>)
-                  -> &'a Block<'a> {
+pub fn trans_loop<'a>(bcx:&'a Block<'a>,
+                      loop_id: ast::NodeId,
+                      body: &ast::Block)
+                      -> &'a Block<'a> {
     let _icx = push_ctxt("trans_loop");
-    let next_bcx = sub_block(bcx, "next");
-    let body_bcx_in = loop_scope_block(bcx, next_bcx, opt_label, "`loop`",
-                                       body.info());
+    let fcx = bcx.fcx;
+
+    //            bcx
+    //             |
+    //         body_bcx_in
+    //             |
+    //         body_bcx_out
+    //
+    // next_bcx
+    //
+    // Links between body_bcx_in and next_bcx are created by
+    // break statements.
+
+    let next_bcx_in = bcx.fcx.new_id_block("loop_exit", loop_id);
+    let body_bcx_in = bcx.fcx.new_id_block("loop_body", body.id);
+
+    fcx.push_loop_cleanup_scope(loop_id, [next_bcx_in, body_bcx_in]);
+
     Br(bcx, body_bcx_in.llbb);
     let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore);
-    cleanup_and_Br(body_bcx_out, body_bcx_in, body_bcx_in.llbb);
-    return next_bcx;
+    Br(body_bcx_out, body_bcx_in.llbb);
+
+    fcx.pop_loop_cleanup_scope(loop_id);
+
+    return next_bcx_in;
 }
 
-pub fn trans_break_cont<'a>(
-                        bcx: &'a Block<'a>,
-                        opt_label: Option<Name>,
-                        to_end: bool)
-                        -> &'a Block<'a> {
+pub fn trans_break_cont<'a>(bcx: &'a Block<'a>,
+                            expr_id: ast::NodeId,
+                            opt_label: Option<Name>,
+                            exit: uint)
+                            -> &'a Block<'a> {
     let _icx = push_ctxt("trans_break_cont");
-    // Locate closest loop block, outputting cleanup as we go.
-    let mut unwind = bcx;
-    let mut cur_scope = unwind.scope.get();
-    let mut target;
-    loop {
-        cur_scope = match cur_scope {
-            Some(&ScopeInfo {
-                loop_break: Some(brk),
-                loop_label: l,
-                parent,
-                ..
-            }) => {
-                // If we're looking for a labeled loop, check the label...
-                target = if to_end {
-                    brk
-                } else {
-                    unwind
-                };
-                match opt_label {
-                    Some(desired) => match l {
-                        Some(actual) if actual == desired => break,
-                        // If it doesn't match the one we want,
-                        // don't break
-                        _ => parent,
-                    },
-                    None => break,
+    let fcx = bcx.fcx;
+
+    if bcx.unreachable.get() {
+        return bcx;
+    }
+
+    // Locate loop that we will break to
+    let loop_id = match opt_label {
+        None => fcx.top_loop_scope(),
+        Some(_) => {
+            let def_map = bcx.tcx().def_map.borrow();
+            match def_map.get().find(&expr_id) {
+                Some(&ast::DefLabel(loop_id)) => loop_id,
+                ref r => {
+                    bcx.tcx().sess.bug(format!("{:?} in def-map for label", r))
                 }
             }
-            Some(inf) => inf.parent,
-            None => {
-                unwind = match unwind.parent {
-                    Some(bcx) => bcx,
-                        // This is a return from a loop body block
-                        None => {
-                            Store(bcx,
-                                  C_bool(!to_end),
-                                  bcx.fcx.llretptr.get().unwrap());
-                            cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn()));
-                            Unreachable(bcx);
-                            return bcx;
-                        }
-                };
-                unwind.scope.get()
-            }
         }
-    }
-    cleanup_and_Br(bcx, unwind, target.llbb);
-    Unreachable(bcx);
+    };
+
+    // Generate appropriate cleanup code and branch
+    let cleanup_llbb = fcx.normal_exit_block(loop_id, exit);
+    Br(bcx, cleanup_llbb);
+    Unreachable(bcx); // anything afterwards should be ignored
     return bcx;
 }
 
-pub fn trans_break<'a>(bcx: &'a Block<'a>, label_opt: Option<Name>)
-                   -> &'a Block<'a> {
-    return trans_break_cont(bcx, label_opt, true);
+pub fn trans_break<'a>(bcx: &'a Block<'a>,
+                       expr_id: ast::NodeId,
+                       label_opt: Option<Name>)
+                       -> &'a Block<'a> {
+    return trans_break_cont(bcx, expr_id, label_opt, cleanup::EXIT_BREAK);
 }
 
-pub fn trans_cont<'a>(bcx: &'a Block<'a>, label_opt: Option<Name>)
-                  -> &'a Block<'a> {
-    return trans_break_cont(bcx, label_opt, false);
+pub fn trans_cont<'a>(bcx: &'a Block<'a>,
+                      expr_id: ast::NodeId,
+                      label_opt: Option<Name>)
+                      -> &'a Block<'a> {
+    return trans_break_cont(bcx, expr_id, label_opt, cleanup::EXIT_LOOP);
 }
 
-pub fn trans_ret<'a>(bcx: &'a Block<'a>, e: Option<@ast::Expr>)
-                 -> &'a Block<'a> {
+pub fn trans_ret<'a>(bcx: &'a Block<'a>,
+                     e: Option<@ast::Expr>)
+                     -> &'a Block<'a> {
     let _icx = push_ctxt("trans_ret");
+    let fcx = bcx.fcx;
     let mut bcx = bcx;
     let dest = match bcx.fcx.llretptr.get() {
         None => expr::Ignore,
@@ -322,7 +311,8 @@ pub fn trans_ret<'a>(bcx: &'a Block<'a>, e: Option<@ast::Expr>)
         }
         _ => ()
     }
-    cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn()));
+    let cleanup_llbb = fcx.return_exit_block();
+    Br(bcx, cleanup_llbb);
     Unreachable(bcx);
     return bcx;
 }
@@ -338,8 +328,8 @@ pub fn trans_fail_expr<'a>(
         Some(arg_expr) => {
             let ccx = bcx.ccx();
             let tcx = ccx.tcx;
-            let arg_datum = unpack_datum!(
-                bcx, expr::trans_to_datum(bcx, arg_expr));
+            let arg_datum =
+                unpack_datum!(bcx, expr::trans_to_lvalue(bcx, arg_expr, "fail"));
 
             if ty::type_is_str(arg_datum.ty) {
                 let (lldata, _) = arg_datum.get_vec_base_and_len_no_root(bcx);
index e7eab31ac14e7f02f4579aac7d0a3aac8adcc208..467501449b8d5c8b8488c44c4a5440eb1cba0a17 100644 (file)
 // except according to those terms.
 
 /*!
- *
- * A `Datum` contains all the information you need to describe the LLVM
- * translation of a Rust value.  It describes where the value is stored,
- * what Rust type the value has, whether it is addressed by reference,
- * and so forth.
- *
- * The idea of a datum is that, to the extent possible, you should not
- * care about these details, but rather use the methods on the Datum
- * type to "do what you want to do".  For example, you can simply call
- * `copy_to()` or `move_to()` to copy or move the value into a new
- * home.
- *
- * # Datum location
- *
- * The primary two fields of a datum are the `val` and the `mode`.
- * The `val` is an LLVM value ref.  It may either *be the value* that
- * is being tracked, or it may be a *pointer to the value being
- * tracked*.  This is specified in the `mode` field, which can either
- * be `ByValue` or `ByRef`, respectively.  The (Rust) type of the
- * value stored in the datum is indicated in the field `ty`.
- *
- * Generally speaking, you probably do not want to access the `val` field
- * unless you know what mode the value is in.  Instead you should use one
- * of the following accessors:
- *
- * - `to_value_llval()` converts to by-value
- * - `to_ref_llval()` converts to by-ref, allocating a stack slot if necessary
- * - `to_appropriate_llval()` converts to by-value if this is an
- *   immediate type, by-ref otherwise.  This is particularly
- *   convenient for interfacing with the various code floating around
- *   that predates datums.
- *
- * # Datum cleanup styles
- *
- * Each datum carries with it an idea of how its value will be cleaned
- * up.  This is primarily determined by the mode: a `ByValue` datum
- * will always be cleaned up by revoking cleanup using
- * `revoke_clean()`, because there is no other option. By ref datums
- * can sometimes be cleaned up via `revoke_clean` (in particular,
- * by-ref datums that originated from rvalues), but sometimes they
- * must be zeroed. This is indicated by the `DatumCleanup`
- * parameter. Note that zeroing a by-ref datum *always works* to
- * cancel the cleanup, but using `revoke_clean` is preferable since
- * there is no runtime cost. Some older parts of the code (notably
- * `match_`, at least at the time of this writing) rely on this and
- * only use zeroing.
- *
- * # Copying, moving, and storing
- *
- * There are three methods for moving the value into a new
- * location:
- *
- * - `copy_to()` will copy the value into a new location, meaning that
- *    the value is first mem-copied and then the new location is "taken"
- *    via the take glue, in effect creating a deep clone.
- *
- * - `move_to()` will copy the value, meaning that the value is mem-copied
- *   into its new home and then the cleanup on the this datum is revoked.
- *   This is a "shallow" clone.  After `move_to()`, the current datum
- *   is invalid and should no longer be used.
- *
- * - `store_to()` either performs a copy or a move depending on the
- *   Rust type of the datum.
- *
- * # Scratch datum
- *
- * Sometimes you just need some temporary scratch space.  The
- * `scratch_datum()` function will yield you up a by-ref datum that
- * points into the stack.  It's your responsibility to ensure that
- * whatever you put in there gets cleaned up etc.
- *
- * # Other actions
- *
- * There are various other helper methods on Datum, such as `deref()`,
- * `get_base_and_len()` and so forth.  These are documented on the
- * methods themselves.  Most are only suitable for some types of
- * values. */
-
+ * See the section on datums in `doc.rs` for an overview of what
+ * Datums are and how they are intended to be used.
+ */
 
 use lib;
 use lib::llvm::ValueRef;
 use middle::trans::base::*;
 use middle::trans::build::*;
 use middle::trans::common::*;
-use middle::trans::common;
+use middle::trans::cleanup;
+use middle::trans::cleanup::CleanupMethods;
 use middle::trans::expr;
 use middle::trans::glue;
 use middle::trans::tvec;
 use middle::trans::type_of;
 use middle::trans::write_guard;
 use middle::ty;
-use util::common::indenter;
-use util::ppaux::ty_to_str;
+use util::ppaux::{ty_to_str};
 
-use std::uint;
 use syntax::ast;
 use syntax::codemap::Span;
 
-#[deriving(Eq)]
-pub enum CopyAction {
   INIT,
-    DROP_EXISTING
-}
-
+/**
+ * A `Datum` encapsulates the result of evaluating an expression.  It
* describes where the value is stored, what Rust type the value has,
+ * whether it is addressed by reference, and so forth. Please refer
+ * the section on datums in `doc.rs` for more details.
+ */
 #[deriving(Clone)]
-pub struct Datum {
+pub struct Datum<K> {
     /// The llvm value.  This is either a pointer to the Rust value or
-    /// the value itself, depending on `mode` below.
+    /// the value itself, depending on `kind` below.
     val: ValueRef,
 
     /// The rust type of the value.
     ty: ty::t,
 
     /// Indicates whether this is by-ref or by-value.
-    mode: DatumMode,
+    kind: K,
 }
 
-pub struct DatumBlock<'a> {
+pub struct DatumBlock<'a, K> {
     bcx: &'a Block<'a>,
-    datum: Datum,
+    datum: Datum<K>,
+}
+
+pub enum Expr {
+    /// a fresh value that was produced and which has no cleanup yet
+    /// because it has not yet "landed" into its permanent home
+    RvalueExpr(Rvalue),
+
+    /// `val` is a pointer into memory for which a cleanup is scheduled
+    /// (and thus has type *T). If you move out of an Lvalue, you must
+    /// zero out the memory (FIXME #5016).
+    LvalueExpr,
+}
+
+#[deriving(Clone)]
+pub struct Lvalue;
+
+pub struct Rvalue {
+    mode: RvalueMode
+}
+
+pub fn Rvalue(m: RvalueMode) -> Rvalue {
+    Rvalue { mode: m }
 }
 
-#[deriving(Clone, Eq, IterBytes)]
-pub enum DatumMode {
-    /// `val` is a pointer to the actual value (and thus has type *T).
-    /// The argument indicates how to cancel cleanup of this datum if
-    /// the value is moved elsewhere, which can either be by zeroing
-    /// the memory or by canceling a registered cleanup.
-    ByRef(DatumCleanup),
+// Make Datum linear for more type safety.
+impl Drop for Rvalue {
+    fn drop(&mut self) { }
+}
+
+#[deriving(Eq, IterBytes)]
+pub enum RvalueMode {
+    /// `val` is a pointer to the actual value (and thus has type *T)
+    ByRef,
 
     /// `val` is the actual value (*only used for immediates* like ints, ptrs)
     ByValue,
 }
 
-impl DatumMode {
-    pub fn is_by_ref(&self) -> bool {
-        match *self { ByRef(_) => true, ByValue => false }
-    }
+pub fn Datum<K:KindOps>(val: ValueRef, ty: ty::t, kind: K) -> Datum<K> {
+    Datum { val: val, ty: ty, kind: kind }
+}
 
-    pub fn is_by_value(&self) -> bool {
-        match *self { ByRef(_) => false, ByValue => true }
-    }
+pub fn DatumBlock<'a, K>(bcx: &'a Block<'a>,
+                         datum: Datum<K>)
+                         -> DatumBlock<'a, K> {
+    DatumBlock { bcx: bcx, datum: datum }
 }
 
-/// See `Datum cleanup styles` section at the head of this module.
-#[deriving(Clone, Eq, IterBytes)]
-pub enum DatumCleanup {
-    RevokeClean,
-    ZeroMem
+pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum<Rvalue> {
+    return Datum(val, ty, Rvalue(ByValue));
 }
 
-pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum {
-    return Datum {val: val, ty: ty, mode: ByValue};
+pub fn immediate_rvalue_bcx<'a>(bcx: &'a Block<'a>,
+                                val: ValueRef,
+                                ty: ty::t)
+                                -> DatumBlock<'a, Rvalue> {
+    return DatumBlock(bcx, immediate_rvalue(val, ty))
 }
 
-pub fn immediate_rvalue_bcx<'a>(bcx: &'a Block<'a>, val: ValueRef, ty: ty::t)
-                            -> DatumBlock<'a> {
-    DatumBlock {
-        bcx: bcx,
-        datum: immediate_rvalue(val, ty),
-    }
+
+pub fn lvalue_scratch_datum<'a, A>(bcx: &'a Block<'a>,
+                                   ty: ty::t,
+                                   name: &str,
+                                   zero: bool,
+                                   scope: cleanup::ScopeId,
+                                   arg: A,
+                                   populate: |A, &'a Block<'a>, ValueRef|
+                                             -> &'a Block<'a>)
+                                   -> DatumBlock<'a, Lvalue> {
+    /*!
+     * Allocates temporary space on the stack using alloca() and
+     * returns a by-ref Datum pointing to it. The memory will be
+     * dropped upon exit from `scope`. The callback `populate` should
+     * initialize the memory. If `zero` is true, the space will be
+     * zeroed when it is allocated; this is not necessary unless `bcx`
+     * does not dominate the end of `scope`.
+     */
+
+    let llty = type_of::type_of(bcx.ccx(), ty);
+    let scratch = alloca_maybe_zeroed(bcx, llty, name, zero);
+
+    // Subtle. Populate the scratch memory *before* scheduling cleanup.
+    let bcx = populate(arg, bcx, scratch);
+    bcx.fcx.schedule_drop_mem(scope, scratch, ty);
+
+    DatumBlock(bcx, Datum(scratch, ty, Lvalue))
 }
 
-pub fn scratch_datum(bcx: &Block, ty: ty::t, name: &str, zero: bool)
-                     -> Datum {
+pub fn rvalue_scratch_datum(bcx: &Block,
+                            ty: ty::t,
+                            name: &str)
+                            -> Datum<Rvalue> {
     /*!
      * Allocates temporary space on the stack using alloca() and
      * returns a by-ref Datum pointing to it.  If `zero` is true, the
@@ -185,526 +156,376 @@ pub fn scratch_datum(bcx: &Block, ty: ty::t, name: &str, zero: bool)
      */
 
     let llty = type_of::type_of(bcx.ccx(), ty);
-    let scratch = alloca_maybe_zeroed(bcx, llty, name, zero);
-    Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) }
+    let scratch = alloca_maybe_zeroed(bcx, llty, name, false);
+    Datum(scratch, ty, Rvalue(ByRef))
+}
+
+pub fn is_by_value_type(ccx: &CrateContext, ty: ty::t) -> bool {
+    appropriate_rvalue_mode(ccx, ty) == ByValue
 }
 
-pub fn appropriate_mode(ccx: &CrateContext, ty: ty::t) -> DatumMode {
+pub fn appropriate_rvalue_mode(ccx: &CrateContext, ty: ty::t) -> RvalueMode {
     /*!
      * Indicates the "appropriate" mode for this value,
      * which is either by ref or by value, depending
      * on whether type is immediate or not.
      */
 
-    if ty::type_is_voidish(ccx.tcx, ty) {
+    if type_is_zero_size(ccx, ty) {
         ByValue
     } else if type_is_immediate(ccx, ty) {
         ByValue
     } else {
-        ByRef(RevokeClean)
+        ByRef
     }
 }
 
-impl Datum {
-    pub fn store_to<'a>(
-                    &self,
-                    bcx: &'a Block<'a>,
-                    action: CopyAction,
-                    dst: ValueRef)
-                    -> &'a Block<'a> {
-        /*!
-         *
-         * Stores this value into its final home.  This moves if
-         * `id` is located in the move table, but copies otherwise.
-         */
-
-        if ty::type_moves_by_default(bcx.tcx(), self.ty) {
-            self.move_to(bcx, action, dst)
-        } else {
-            self.copy_to(bcx, action, dst)
-        }
+fn add_rvalue_clean(mode: RvalueMode,
+                    fcx: &FunctionContext,
+                    scope: cleanup::ScopeId,
+                    val: ValueRef,
+                    ty: ty::t) {
+    match mode {
+        ByValue => { fcx.schedule_drop_immediate(scope, val, ty); }
+        ByRef => { fcx.schedule_drop_mem(scope, val, ty); }
     }
+}
 
-    pub fn store_to_dest<'a>(&self, bcx: &'a Block<'a>, dest: expr::Dest)
-                         -> &'a Block<'a> {
-        match dest {
-            expr::Ignore => {
-                return bcx;
-            }
-            expr::SaveIn(addr) => {
-                return self.store_to(bcx, INIT, addr);
-            }
-        }
-    }
+pub trait KindOps {
 
-    pub fn store_to_datum<'a>(
-                          &self,
-                          bcx: &'a Block<'a>,
-                          action: CopyAction,
-                          datum: Datum)
-                          -> &'a Block<'a> {
-        debug!("store_to_datum(self={}, action={:?}, datum={})",
-               self.to_str(bcx.ccx()), action, datum.to_str(bcx.ccx()));
-        assert!(datum.mode.is_by_ref());
-        self.store_to(bcx, action, datum.val)
-    }
-
-    pub fn move_to_datum<'a>(
-                         &self,
-                         bcx: &'a Block<'a>,
-                         action: CopyAction,
-                         datum: Datum)
-                         -> &'a Block<'a> {
-        assert!(datum.mode.is_by_ref());
-        self.move_to(bcx, action, datum.val)
-    }
-
-    pub fn copy_to_datum<'a>(
-                         &self,
-                         bcx: &'a Block<'a>,
-                         action: CopyAction,
-                         datum: Datum)
-                         -> &'a Block<'a> {
-        assert!(datum.mode.is_by_ref());
-        self.copy_to(bcx, action, datum.val)
-    }
-
-    pub fn copy_to<'a>(
-                   &self,
-                   bcx: &'a Block<'a>,
-                   action: CopyAction,
-                   dst: ValueRef)
-                   -> &'a Block<'a> {
-        /*!
-         *
-         * Copies the value into `dst`, which should be a pointer to a
-         * memory location suitable for `self.ty`.  You PROBABLY want
-         * `store_to()` instead, which will move if possible but copy if
-         * neccessary. */
+    /**
+     * Take appropriate action after the value in `datum` has been
+     * stored to a new location.
+     */
+    fn post_store<'a>(&self,
+                      bcx: &'a Block<'a>,
+                      val: ValueRef,
+                      ty: ty::t)
+                      -> &'a Block<'a>;
+
+    /**
+     * True if this mode is a reference mode, meaning that the datum's
+     * val field is a pointer to the actual value
+     */
+    fn is_by_ref(&self) -> bool;
 
-        let _icx = push_ctxt("copy_to");
+    /**
+     * Converts to an Expr kind
+     */
+    fn to_expr_kind(self) -> Expr;
 
-        if ty::type_is_voidish(bcx.tcx(), self.ty) {
-            return bcx;
-        }
+}
 
-        debug!("copy_to(self={}, action={:?}, dst={})",
-               self.to_str(bcx.ccx()), action, bcx.val_to_str(dst));
-
-        // Watch out for the case where we are writing the copying the
-        // value into the same location we read it out from.  We want
-        // to avoid the case where we drop the existing value, which
-        // frees it, and then overwrite it with itself (which has been
-        // freed).
-        if action == DROP_EXISTING &&
-            ty::type_needs_drop(bcx.tcx(), self.ty)
-        {
-            match self.mode {
-                ByRef(_) => {
-                    let cast = PointerCast(bcx, dst, val_ty(self.val));
-                    let cmp = ICmp(bcx, lib::llvm::IntNE, cast, self.val);
-                    with_cond(bcx, cmp, |bcx| {
-                        self.copy_to_no_check(bcx, action, dst)
-                    })
-                }
-                ByValue => {
-                    self.copy_to_no_check(bcx, action, dst)
-                }
-            }
-        } else {
-            self.copy_to_no_check(bcx, action, dst)
-        }
+impl KindOps for Rvalue {
+    fn post_store<'a>(&self,
+                      bcx: &'a Block<'a>,
+                      _val: ValueRef,
+                      _ty: ty::t)
+                      -> &'a Block<'a> {
+        // No cleanup is scheduled for an rvalue, so we don't have
+        // to do anything after a move to cancel or duplicate it.
+        bcx
     }
 
-    pub fn copy_to_no_check<'a>(
-                            &self,
-                            bcx: &'a Block<'a>,
-                            action: CopyAction,
-                            dst: ValueRef)
-                            -> &'a Block<'a> {
-        /*!
-         *
-         * A helper for `copy_to()` which does not check to see if we
-         * are copying to/from the same value. */
+    fn is_by_ref(&self) -> bool {
+        self.mode == ByRef
+    }
 
-        let _icx = push_ctxt("copy_to_no_check");
-        let mut bcx = bcx;
+    fn to_expr_kind(self) -> Expr {
+        RvalueExpr(self)
+    }
+}
 
-        if action == DROP_EXISTING {
-            bcx = glue::drop_ty(bcx, dst, self.ty);
-        }
+impl KindOps for Lvalue {
+    fn post_store<'a>(&self,
+                      bcx: &'a Block<'a>,
+                      val: ValueRef,
+                      ty: ty::t)
+                      -> &'a Block<'a> {
+        /*!
+         * If an lvalue is moved, we must zero out the memory in which
+         * it resides so as to cancel cleanup. If an @T lvalue is
+         * copied, we must increment the reference count.
+         */
 
-        match self.mode {
-            ByValue => {
-                Store(bcx, self.val, dst);
-            }
-            ByRef(_) => {
-                memcpy_ty(bcx, dst, self.val, self.ty);
+        if ty::type_needs_drop(bcx.tcx(), ty) {
+            if ty::type_moves_by_default(bcx.tcx(), ty) {
+                // cancel cleanup of affine values by zeroing out
+                let () = zero_mem(bcx, val, ty);
+                bcx
+            } else {
+                // incr. refcount for @T or newtype'd @T
+                glue::take_ty(bcx, val, ty)
             }
+        } else {
+            bcx
         }
-
-        return glue::take_ty(bcx, dst, self.ty);
     }
 
-    // This works like copy_val, except that it deinitializes the source.
-    // Since it needs to zero out the source, src also needs to be an lval.
-    //
-    pub fn move_to<'a>(
-                   &self,
-                   bcx: &'a Block<'a>,
-                   action: CopyAction,
-                   dst: ValueRef)
-                   -> &'a Block<'a> {
-        let _icx = push_ctxt("move_to");
-        let mut bcx = bcx;
+    fn is_by_ref(&self) -> bool {
+        true
+    }
 
-        debug!("move_to(self={}, action={:?}, dst={})",
-               self.to_str(bcx.ccx()), action, bcx.val_to_str(dst));
+    fn to_expr_kind(self) -> Expr {
+        LvalueExpr
+    }
+}
 
-        if ty::type_is_voidish(bcx.tcx(), self.ty) {
-            return bcx;
+impl KindOps for Expr {
+    fn post_store<'a>(&self,
+                      bcx: &'a Block<'a>,
+                      val: ValueRef,
+                      ty: ty::t)
+                      -> &'a Block<'a> {
+        match *self {
+            LvalueExpr => Lvalue.post_store(bcx, val, ty),
+            RvalueExpr(ref r) => r.post_store(bcx, val, ty),
         }
+    }
 
-        if action == DROP_EXISTING {
-            bcx = glue::drop_ty(bcx, dst, self.ty);
+    fn is_by_ref(&self) -> bool {
+        match *self {
+            LvalueExpr => Lvalue.is_by_ref(),
+            RvalueExpr(ref r) => r.is_by_ref()
         }
+    }
 
-        match self.mode {
-            ByRef(_) => {
-                memcpy_ty(bcx, dst, self.val, self.ty);
-            }
-            ByValue => {
-                Store(bcx, self.val, dst);
-            }
-        }
+    fn to_expr_kind(self) -> Expr {
+        self
+    }
+}
 
-        self.cancel_clean(bcx);
+impl Datum<Rvalue> {
+    pub fn add_clean(self,
+                     fcx: &FunctionContext,
+                     scope: cleanup::ScopeId)
+                     -> ValueRef {
+        /*!
+         * Schedules a cleanup for this datum in the given scope.
+         * That means that this datum is no longer an rvalue datum;
+         * hence, this function consumes the datum and returns the
+         * contained ValueRef.
+         */
 
-        return bcx;
+        add_rvalue_clean(self.kind.mode, fcx, scope, self.val, self.ty);
+        self.val
     }
 
-    pub fn add_clean(&self, bcx: &Block) {
+    pub fn to_lvalue_datum_in_scope<'a>(self,
+                                        bcx: &'a Block<'a>,
+                                        name: &str,
+                                        scope: cleanup::ScopeId)
+                                        -> DatumBlock<'a, Lvalue> {
         /*!
-         * Schedules this datum for cleanup in `bcx`.  The datum
-         * must be an rvalue.
+         * Returns an lvalue datum (that is, a by ref datum with
+         * cleanup scheduled). If `self` is not already an lvalue,
+         * cleanup will be scheduled in the temporary scope for `expr_id`.
          */
+        let fcx = bcx.fcx;
 
-        match self.mode {
-            ByValue => {
-                add_clean_temp_immediate(bcx, self.val, self.ty);
+        match self.kind.mode {
+            ByRef => {
+                add_rvalue_clean(ByRef, fcx, scope, self.val, self.ty);
+                DatumBlock(bcx, Datum(self.val, self.ty, Lvalue))
             }
-            ByRef(RevokeClean) => {
-                add_clean_temp_mem(bcx, self.val, self.ty);
+
+            ByValue => {
+                lvalue_scratch_datum(
+                    bcx, self.ty, name, false, scope, self,
+                    |this, bcx, llval| this.store_to(bcx, llval))
             }
-            ByRef(ZeroMem) => {
-                add_clean(bcx, self.val, self.ty)
+        }
+    }
+
+    pub fn to_ref_datum<'a>(self, bcx: &'a Block<'a>) -> DatumBlock<'a, Rvalue> {
+        let mut bcx = bcx;
+        match self.kind.mode {
+            ByRef => DatumBlock(bcx, self),
+            ByValue => {
+                let scratch = rvalue_scratch_datum(bcx, self.ty, "to_ref");
+                bcx = self.store_to(bcx, scratch.val);
+                DatumBlock(bcx, scratch)
             }
         }
     }
 
-    pub fn cancel_clean(&self, bcx: &Block) {
-        if ty::type_needs_drop(bcx.tcx(), self.ty) {
-            match self.mode {
-                ByValue |
-                ByRef(RevokeClean) => {
-                    revoke_clean(bcx, self.val);
-                }
-                ByRef(ZeroMem) => {
-                    // Lvalues which potentially need to be dropped
-                    // must be passed by ref, so that we can zero them
-                    // out.
-                    zero_mem(bcx, self.val, self.ty);
+    pub fn to_appropriate_datum<'a>(self,
+                                    bcx: &'a Block<'a>)
+                                    -> DatumBlock<'a, Rvalue> {
+        match self.appropriate_rvalue_mode(bcx.ccx()) {
+            ByRef => {
+                self.to_ref_datum(bcx)
+            }
+            ByValue => {
+                match self.kind.mode {
+                    ByValue => DatumBlock(bcx, self),
+                    ByRef => {
+                        let llval = load(bcx, self.val, self.ty);
+                        DatumBlock(bcx, Datum(llval, self.ty, Rvalue(ByValue)))
+                    }
                 }
             }
         }
     }
+}
 
-    pub fn to_str(&self, ccx: &CrateContext) -> ~str {
-        format!("Datum \\{ val={}, ty={}, mode={:?} \\}",
-             ccx.tn.val_to_str(self.val),
-             ty_to_str(ccx.tcx, self.ty),
-             self.mode)
+/**
+ * Methods suitable for "expr" datums that could be either lvalues or
+ * rvalues. These include coercions into lvalues/rvalues but also a number
+ * of more general operations. (Some of those operations could be moved to
+ * the more general `impl<K> Datum<K>`, but it's convenient to have them
+ * here since we can `match self.kind` rather than having to implement
+ * generic methods in `KindOps`.)
+ */
+impl Datum<Expr> {
+    fn match_kind<R>(self,
+                     if_lvalue: |Datum<Lvalue>| -> R,
+                     if_rvalue: |Datum<Rvalue>| -> R)
+                     -> R {
+        let Datum { val, ty, kind } = self;
+        match kind {
+            LvalueExpr => if_lvalue(Datum(val, ty, Lvalue)),
+            RvalueExpr(r) => if_rvalue(Datum(val, ty, r)),
+        }
     }
 
-    pub fn to_value_datum(&self, bcx: &Block) -> Datum {
-        /*!
-         *
-         * Yields a by-value form of this datum.  This may involve
-         * creation of a temporary stack slot.  The value returned by
-         * this function is not separately rooted from this datum, so
-         * it will not live longer than the current datum. */
-
-        match self.mode {
-            ByValue => *self,
-            ByRef(_) => {
-                Datum {val: self.to_value_llval(bcx), mode: ByValue,
-                       ty: self.ty}
-            }
-        }
+    pub fn is_by_ref(&self) -> bool {
+        self.kind.is_by_ref()
     }
 
-    pub fn to_value_llval(&self, bcx: &Block) -> ValueRef {
+    pub fn assert_lvalue(self, bcx: &Block) -> Datum<Lvalue> {
         /*!
-         *
-         * Yields the value itself. */
+         * Asserts that this datum *is* an lvalue and returns it.
+         */
 
-        if ty::type_is_voidish(bcx.tcx(), self.ty) {
-            C_nil()
-        } else {
-            match self.mode {
-                ByValue => self.val,
-                ByRef(_) => {
-                    if ty::type_is_bool(self.ty) {
-                        LoadRangeAssert(bcx, self.val, 0, 2, lib::llvm::True)
-                    } else {
-                        Load(bcx, self.val)
-                    }
-                }
-            }
-        }
+        self.match_kind(
+            |d| d,
+            |_| bcx.sess().bug("assert_lvalue given rvalue"))
     }
 
-    pub fn to_ref_datum(&self, bcx: &Block) -> Datum {
+    pub fn assert_rvalue(self, bcx: &Block) -> Datum<Rvalue> {
         /*!
-         * Yields a by-ref form of this datum.  This may involve
-         * creation of a temporary stack slot.  The value returned by
-         * this function is not separately rooted from this datum, so
-         * it will not live longer than the current datum.
+         * Asserts that this datum *is* an lvalue and returns it.
          */
 
-        match self.mode {
-            ByRef(_) => *self,
-            ByValue => {
-                Datum {val: self.to_ref_llval(bcx), mode: ByRef(RevokeClean),
-                       ty: self.ty}
-            }
-        }
+        self.match_kind(
+            |_| bcx.sess().bug("assert_rvalue given lvalue"),
+            |r| r)
     }
 
-    pub fn to_ref_llval(&self, bcx: &Block) -> ValueRef {
-        match self.mode {
-            ByRef(_) => self.val,
-            ByValue => {
-                if ty::type_is_voidish(bcx.tcx(), self.ty) {
-                    C_null(type_of::type_of(bcx.ccx(), self.ty).ptr_to())
-                } else {
-                    let slot = alloc_ty(bcx, self.ty, "");
-                    // The store created here can be modified through a reference, for example:
-                    //
-                    //     // free the old allocation, and change the pointer to a new allocation
-                    //     fn foo(x: &mut ~u8) {
-                    //         *x = ~5;
-                    //     }
-                    //
-                    //     foo(&mut ~5);
-                    Store(bcx, self.val, slot);
-                    // The old cleanup needs to be cancelled, in order for the destructor to observe
-                    // any changes made through the reference.
-                    self.cancel_clean(bcx);
-                    add_clean_temp_mem(bcx, slot, self.ty);
-                    slot
-                }
+    pub fn store_to_dest<'a>(self,
+                             bcx: &'a Block<'a>,
+                             dest: expr::Dest,
+                             expr_id: ast::NodeId)
+                             -> &'a Block<'a> {
+        match dest {
+            expr::Ignore => {
+                self.add_clean_if_rvalue(bcx, expr_id);
+                bcx
+            }
+            expr::SaveIn(addr) => {
+                self.store_to(bcx, addr)
             }
         }
     }
 
-    pub fn appropriate_mode(&self, ccx: &CrateContext) -> DatumMode {
-        /*! See the `appropriate_mode()` function */
-
-        appropriate_mode(ccx, self.ty)
-    }
-
-    pub fn to_appropriate_llval(&self, bcx: &Block) -> ValueRef {
+    pub fn add_clean_if_rvalue<'a>(self,
+                                   bcx: &'a Block<'a>,
+                                   expr_id: ast::NodeId) {
         /*!
-         *
-         * Yields an llvalue with the `appropriate_mode()`. */
+         * Arranges cleanup for `self` if it is an rvalue. Use when
+         * you are done working with a value that may need drop.
+         */
 
-        match self.appropriate_mode(bcx.ccx()) {
-            ByValue => self.to_value_llval(bcx),
-            ByRef(_) => self.to_ref_llval(bcx)
-        }
+        self.match_kind(
+            |_| { /* Nothing to do, cleanup already arranged */ },
+            |r| {
+                let scope = cleanup::temporary_scope(bcx.tcx(), expr_id);
+                r.add_clean(bcx.fcx, scope);
+            })
     }
 
-    pub fn to_appropriate_datum(&self, bcx: &Block) -> Datum {
+    pub fn clean<'a>(self,
+                     bcx: &'a Block<'a>,
+                     name: &'static str,
+                     expr_id: ast::NodeId)
+                     -> &'a Block<'a> {
         /*!
-         *
-         * Yields a datum with the `appropriate_mode()`. */
+         * Ensures that `self` will get cleaned up, if it is not an lvalue
+         * already.
+         */
 
-        match self.appropriate_mode(bcx.ccx()) {
-            ByValue => self.to_value_datum(bcx),
-            ByRef(_) => self.to_ref_datum(bcx)
-        }
+        self.to_lvalue_datum(bcx, name, expr_id).bcx
     }
 
-    pub fn get_element(&self,
-                       bcx: &Block,
-                       ty: ty::t,
-                       source: DatumCleanup,
-                       gep: |ValueRef| -> ValueRef)
-                       -> Datum {
-        let base_val = self.to_ref_llval(bcx);
-        Datum {
-            val: gep(base_val),
-            mode: ByRef(source),
-            ty: ty,
-        }
+    pub fn to_lvalue_datum<'a>(self,
+                               bcx: &'a Block<'a>,
+                               name: &str,
+                               expr_id: ast::NodeId)
+                               -> DatumBlock<'a, Lvalue> {
+        self.match_kind(
+            |l| DatumBlock(bcx, l),
+            |r| {
+                let scope = cleanup::temporary_scope(bcx.tcx(), expr_id);
+                r.to_lvalue_datum_in_scope(bcx, name, scope)
+            })
     }
 
-    pub fn drop_val<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
-        if !ty::type_needs_drop(bcx.tcx(), self.ty) {
-            return bcx;
-        }
-
-        return match self.mode {
-            ByRef(_) => glue::drop_ty(bcx, self.val, self.ty),
-            ByValue => glue::drop_ty_immediate(bcx, self.val, self.ty)
-        };
-    }
-
-    pub fn box_body(&self, bcx: &Block) -> Datum {
+    pub fn to_rvalue_datum<'a>(self,
+                               bcx: &'a Block<'a>,
+                               name: &'static str)
+                               -> DatumBlock<'a, Rvalue> {
         /*!
-         *
-         * This datum must represent an @T or ~T box.  Returns a new
-         * by-ref datum of type T, pointing at the contents. */
-
-        let (content_ty, header) = match ty::get(self.ty).sty {
-            ty::ty_box(typ) => (typ, true),
-            ty::ty_uniq(mt) => (mt.ty, false),
-            ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
-                let unit_ty = ty::sequence_element_type(bcx.tcx(), self.ty);
-                let unboxed_vec_ty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
-                (unboxed_vec_ty, true)
-            }
-            _ => {
-                bcx.tcx().sess.bug(format!(
-                    "box_body() invoked on non-box type {}",
-                    ty_to_str(bcx.tcx(), self.ty)));
-            }
-        };
-
-        if !header && !ty::type_contents(bcx.tcx(), content_ty).owns_managed() {
-            let ptr = self.to_value_llval(bcx);
-            let ty = type_of::type_of(bcx.ccx(), content_ty);
-            let body = PointerCast(bcx, ptr, ty.ptr_to());
-            Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
-        } else { // has a header
-            let ptr = self.to_value_llval(bcx);
-            let body = opaque_box_body(bcx, content_ty, ptr);
-            Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
-        }
-    }
+         * Ensures that we have an rvalue datum (that is, a datum with
+         * no cleanup scheduled).
+         */
 
-    pub fn to_rptr(&self, bcx: &Block) -> Datum {
-        //! Returns a new datum of region-pointer type containing the
-        //! the same ptr as this datum (after converting to by-ref
-        //! using `to_ref_llval()`).
-
-        // Convert to ref, yielding lltype *T.  Then create a Rust
-        // type &'static T (which translates to *T).  Construct new
-        // result (which will be by-value).  Note that it is not
-        // significant *which* region we pick here.
-        let llval = self.to_ref_llval(bcx);
-        let rptr_ty = ty::mk_imm_rptr(bcx.tcx(), ty::ReStatic,
-                                      self.ty);
-        Datum {val: llval, ty: rptr_ty, mode: ByValue}
-    }
-
-    /// bcx: Block wherein to generate insns.
-    /// span: Location where deref occurs.
-    /// expr_id: ID of deref expr.
-    /// derefs: Number of times deref'd already.
-    /// is_auto: If true, only deref if auto-derefable.
-    pub fn try_deref<'a>(
-                     &self,
-                     bcx: &'a Block<'a>,
-                     span: Span,
-                     expr_id: ast::NodeId,
-                     derefs: uint,
-                     is_auto: bool)
-                     -> (Option<Datum>, &'a Block<'a>) {
-        debug!("try_deref(expr_id={:?}, derefs={:?}, is_auto={}, self={:?})",
-               expr_id, derefs, is_auto, self.to_str(bcx.ccx()));
-
-        let bcx =
-            write_guard::root_and_write_guard(
-                self, bcx, span, expr_id, derefs);
-
-        match ty::get(self.ty).sty {
-            ty::ty_box(_) | ty::ty_uniq(_) => {
-                return (Some(self.box_body(bcx)), bcx);
-            }
-            ty::ty_ptr(mt) => {
-                if is_auto { // unsafe ptrs are not AUTO-derefable
-                    return (None, bcx);
-                } else {
-                    return (Some(deref_ptr(bcx, self, mt.ty)), bcx);
+        let mut bcx = bcx;
+        self.match_kind(
+            |l| {
+                match l.appropriate_rvalue_mode(bcx.ccx()) {
+                    ByRef => {
+                        let scratch = rvalue_scratch_datum(bcx, l.ty, name);
+                        bcx = l.store_to(bcx, scratch.val);
+                        DatumBlock(bcx, scratch)
+                    }
+                    ByValue => {
+                        let v = load(bcx, l.val, l.ty);
+                        l.kind.post_store(bcx, l.val, l.ty);
+                        DatumBlock(bcx, Datum(v, l.ty, Rvalue(ByValue)))
+                    }
                 }
-            }
-            ty::ty_rptr(_, mt) => {
-                return (Some(deref_ptr(bcx, self, mt.ty)), bcx);
-            }
-            _ => { // not derefable.
-                return (None, bcx);
-            }
-        }
-
-        fn deref_ptr(bcx: &Block, lv: &Datum, ty: ty::t) -> Datum {
-            Datum {
-                val: lv.to_value_llval(bcx),
-                ty: ty,
-                mode: ByRef(ZeroMem)
-            }
-        }
+            },
+            |r| DatumBlock(bcx, r))
     }
 
-    /// expr: The deref expression.
-    pub fn deref<'a>(
-                 &self,
-                 bcx: &'a Block<'a>,
-                 expr: &ast::Expr,
-                 derefs: uint)
-                 -> DatumBlock<'a> {
-        match self.try_deref(bcx, expr.span, expr.id, derefs, false) {
-            (Some(lvres), bcx) => DatumBlock { bcx: bcx, datum: lvres },
-            (None, _) => {
-                bcx.ccx().sess.span_bug(expr.span,
-                                        "Cannot deref this expression");
-            }
-        }
+}
+
+/**
+ * Methods suitable only for lvalues. These include the various
+ * operations to extract components out of compound data structures,
+ * such as extracting the field from a struct or a particular element
+ * from an array.
+ */
+impl Datum<Lvalue> {
+    pub fn to_llref(self) -> ValueRef {
+        /*!
+         * Converts a datum into a by-ref value. The datum type must
+         * be one which is always passed by reference.
+         */
+
+        self.val
     }
 
-    pub fn autoderef<'a>(
-                     &self,
-                     bcx: &'a Block<'a>,
-                     span: Span,
-                     expr_id: ast::NodeId,
-                     max: uint)
-                     -> DatumBlock<'a> {
-        let _icx = push_ctxt("autoderef");
-
-        debug!("autoderef(expr_id={}, max={:?}, self={:?})",
-               expr_id, max, self.to_str(bcx.ccx()));
-        let _indenter = indenter();
-
-        let mut datum = *self;
-        let mut derefs = 0u;
-        let mut bcx = bcx;
-        while derefs < max {
-            derefs += 1u;
-            match datum.try_deref(bcx, span, expr_id, derefs, true) {
-                (None, new_bcx) => { bcx = new_bcx; break }
-                (Some(datum_deref), new_bcx) => {
-                    datum = datum_deref;
-                    bcx = new_bcx;
-                }
-            }
+    pub fn get_element(&self,
+                       ty: ty::t,
+                       gep: |ValueRef| -> ValueRef)
+                       -> Datum<Lvalue> {
+        Datum {
+            val: gep(self.val),
+            kind: Lvalue,
+            ty: ty,
         }
-
-        // either we were asked to deref a specific number of times,
-        // in which case we should have, or we asked to deref as many
-        // times as we can
-        assert!(derefs == max || max == uint::max_value);
-        DatumBlock { bcx: bcx, datum: datum }
     }
 
     pub fn get_vec_base_and_byte_len<'a>(
@@ -728,17 +549,15 @@ pub fn get_vec_base_and_byte_len_no_root(&self, bcx: &Block)
         //! Converts a vector into the slice pair. Des not root
         //! nor perform write guard checks.
 
-        let llval = self.to_appropriate_llval(bcx);
-        tvec::get_base_and_byte_len(bcx, llval, self.ty)
+        tvec::get_base_and_byte_len(bcx, self.val, self.ty)
     }
 
-    pub fn get_vec_base_and_len<'a>(
-                                &self,
-                                mut bcx: &'a Block<'a>,
-                                span: Span,
-                                expr_id: ast::NodeId,
-                                derefs: uint)
-                                -> (&'a Block<'a>, ValueRef, ValueRef) {
+    pub fn get_vec_base_and_len<'a>(&self,
+                                    mut bcx: &'a Block<'a>,
+                                    span: Span,
+                                    expr_id: ast::NodeId,
+                                    derefs: uint)
+                                    -> (&'a Block<'a>, ValueRef, ValueRef) {
         //! Converts a vector into the slice pair. Performs rooting
         //! and write guards checks.
 
@@ -749,12 +568,118 @@ pub fn get_vec_base_and_len<'a>(
     }
 
     pub fn get_vec_base_and_len_no_root<'a>(&self, bcx: &'a Block<'a>)
-                                        -> (ValueRef, ValueRef) {
+                                            -> (ValueRef, ValueRef) {
         //! Converts a vector into the slice pair. Des not root
         //! nor perform write guard checks.
 
-        let llval = self.to_appropriate_llval(bcx);
-        tvec::get_base_and_len(bcx, llval, self.ty)
+        tvec::get_base_and_len(bcx, self.val, self.ty)
+    }
+}
+
+fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef {
+    /*!
+     * Private helper for loading from a by-ref datum. Handles various
+     * special cases where the type gives us better information about
+     * what we are loading.
+     */
+
+    if type_is_zero_size(bcx.ccx(), ty) {
+        C_undef(type_of::type_of(bcx.ccx(), ty))
+    } else if ty::type_is_bool(ty) {
+        LoadRangeAssert(bcx, llptr, 0, 2, lib::llvm::True)
+    } else {
+        Load(bcx, llptr)
+    }
+}
+
+/**
+ * Generic methods applicable to any sort of datum.
+ */
+impl<K:KindOps> Datum<K> {
+    pub fn to_expr_datum(self) -> Datum<Expr> {
+        let Datum { val, ty, kind } = self;
+        Datum { val: val, ty: ty, kind: kind.to_expr_kind() }
+    }
+
+    pub fn store_to<'a>(self,
+                        bcx: &'a Block<'a>,
+                        dst: ValueRef)
+                        -> &'a Block<'a> {
+        /*!
+         * Moves or copies this value into a new home, as appropriate
+         * depending on the type of the datum. This method consumes
+         * the datum, since it would be incorrect to go on using the
+         * datum if the value represented is affine (and hence the value
+         * is moved).
+         */
+
+        self.shallow_copy(bcx, dst);
+
+        self.kind.post_store(bcx, self.val, self.ty)
+    }
+
+    fn shallow_copy<'a>(&self,
+                        bcx: &'a Block<'a>,
+                        dst: ValueRef)
+                        -> &'a Block<'a> {
+        /*!
+         * Helper function that performs a shallow copy of this value
+         * into `dst`, which should be a pointer to a memory location
+         * suitable for `self.ty`. `dst` should contain uninitialized
+         * memory (either newly allocated, zeroed, or dropped).
+         *
+         * This function is private to datums because it leaves memory
+         * in an unstable state, where the source value has been
+         * copied but not zeroed. Public methods are `store_to` (if
+         * you no longer need the source value) or
+         * `shallow_copy_and_take` (if you wish the source value to
+         * remain valid).
+         */
+
+        let _icx = push_ctxt("copy_to_no_check");
+
+        if type_is_zero_size(bcx.ccx(), self.ty) {
+            return bcx;
+        }
+
+        if self.kind.is_by_ref() {
+            memcpy_ty(bcx, dst, self.val, self.ty);
+        } else {
+            Store(bcx, self.val, dst);
+        }
+
+        return bcx;
+    }
+
+    pub fn shallow_copy_and_take<'a>(&self,
+                                     bcx: &'a Block<'a>,
+                                     dst: ValueRef)
+                                     -> &'a Block<'a> {
+        /*!
+         * Copies the value into a new location and runs any necessary
+         * take glue on the new location. This function always
+         * preserves the existing datum as a valid value. Therefore,
+         * it does not consume `self` and, also, cannot be applied to
+         * affine values (since they must never be duplicated).
+         */
+
+        assert!(!ty::type_moves_by_default(bcx.tcx(), self.ty));
+        let mut bcx = bcx;
+        bcx = self.shallow_copy(bcx, dst);
+        glue::take_ty(bcx, dst, self.ty)
+    }
+
+    pub fn to_str(&self, ccx: &CrateContext) -> ~str {
+        format!("Datum({}, {}, {:?})",
+             ccx.tn.val_to_str(self.val),
+             ty_to_str(ccx.tcx, self.ty),
+             self.kind)
+    }
+
+    pub fn appropriate_rvalue_mode(&self, ccx: &CrateContext) -> RvalueMode {
+        /*! See the `appropriate_rvalue_mode()` function */
+
+        appropriate_rvalue_mode(ccx, self.ty)
     }
 
     pub fn root_and_write_guard<'a>(
@@ -767,47 +692,58 @@ pub fn root_and_write_guard<'a>(
         write_guard::root_and_write_guard(self, bcx, span, expr_id, derefs)
     }
 
-    pub fn to_result<'a>(&self, bcx: &'a Block<'a>) -> common::Result<'a> {
-        rslt(bcx, self.to_appropriate_llval(bcx))
-    }
-}
-
-impl<'a> DatumBlock<'a> {
-    pub fn unpack(&self, bcx: &mut &'a Block<'a>) -> Datum {
-        *bcx = self.bcx;
-        return self.datum;
-    }
+    pub fn to_llscalarish<'a>(self, bcx: &'a Block<'a>) -> ValueRef {
+        /*!
+         * Converts `self` into a by-value `ValueRef`. Consumes this
+         * datum (i.e., absolves you of responsibility to cleanup the
+         * value). For this to work, the value must be something
+         * scalar-ish (like an int or a pointer) which (1) does not
+         * require drop glue and (2) is naturally passed around by
+         * value, and not by reference.
+         */
 
-    pub fn assert_by_ref(&self) -> DatumBlock<'a> {
-        assert!(self.datum.mode.is_by_ref());
-        *self
+        assert!(!ty::type_needs_drop(bcx.tcx(), self.ty));
+        assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue);
+        if self.kind.is_by_ref() {
+            load(bcx, self.val, self.ty)
+        } else {
+            self.val
+        }
     }
 
-    pub fn drop_val(&self) -> &'a Block<'a> {
-        self.datum.drop_val(self.bcx)
+    pub fn to_llbool<'a>(self, bcx: &'a Block<'a>) -> ValueRef {
+        assert!(ty::type_is_bool(self.ty) || ty::type_is_bot(self.ty))
+        let cond_val = self.to_llscalarish(bcx);
+        bool_to_i1(bcx, cond_val)
     }
+}
 
-    pub fn store_to(&self, action: CopyAction, dst: ValueRef)
-                    -> &'a Block<'a> {
-        self.datum.store_to(self.bcx, action, dst)
+impl<'a, K:KindOps> DatumBlock<'a, K> {
+    pub fn to_expr_datumblock(self) -> DatumBlock<'a, Expr> {
+        DatumBlock(self.bcx, self.datum.to_expr_datum())
     }
+}
 
-    pub fn copy_to(&self, action: CopyAction, dst: ValueRef)
-                   -> &'a Block<'a> {
-        self.datum.copy_to(self.bcx, action, dst)
+impl<'a> DatumBlock<'a, Expr> {
+    pub fn assert_by_ref(self) -> DatumBlock<'a, Expr> {
+        assert!(self.datum.kind.is_by_ref());
+        self
     }
 
-    pub fn move_to(&self, action: CopyAction, dst: ValueRef)
-                   -> &'a Block<'a> {
-        self.datum.move_to(self.bcx, action, dst)
+    pub fn store_to(self, dst: ValueRef) -> &'a Block<'a> {
+        let DatumBlock { bcx, datum } = self;
+        datum.store_to(bcx, dst)
     }
 
-    pub fn to_value_llval(&self) -> ValueRef {
-        self.datum.to_value_llval(self.bcx)
+    pub fn store_to_dest(self,
+                         dest: expr::Dest,
+                         expr_id: ast::NodeId) -> &'a Block<'a> {
+        let DatumBlock { bcx, datum } = self;
+        datum.store_to_dest(bcx, dest, expr_id)
     }
 
-    pub fn to_result(&self) -> common::Result<'a> {
-        rslt(self.bcx, self.datum.to_appropriate_llval(self.bcx))
+    pub fn shallow_copy(self, dst: ValueRef) -> &'a Block<'a> {
+        self.datum.shallow_copy(self.bcx, dst)
     }
 
     pub fn ccx(&self) -> @CrateContext {
@@ -821,4 +757,9 @@ pub fn tcx(&self) -> ty::ctxt {
     pub fn to_str(&self) -> ~str {
         self.datum.to_str(self.ccx())
     }
+
+    pub fn to_llbool(self) -> Result<'a> {
+        let DatumBlock { datum, bcx } = self;
+        rslt(bcx, datum.to_llbool(bcx))
+    }
 }
index 7e1efcf3a60e061695bcef61857be17e89b30f31..88f38d9f4fd75f274199b6a7411471b06b472457 100644 (file)
@@ -133,7 +133,7 @@ struct List {
 use middle::trans::base;
 use middle::trans::build;
 use middle::trans::common::*;
-use middle::trans::datum;
+use middle::trans::datum::{Datum, Lvalue};
 use middle::trans::machine;
 use middle::trans::type_of;
 use middle::trans::type_::Type;
@@ -396,7 +396,7 @@ pub fn create_match_binding_metadata(bcx: &Block,
                                      variable_ident: ast::Ident,
                                      node_id: ast::NodeId,
                                      span: Span,
-                                     datum: datum::Datum) {
+                                     datum: Datum<Lvalue>) {
     if fn_should_be_ignored(bcx.fcx) {
         return;
     }
@@ -2147,10 +2147,6 @@ fn create_pointer_to_box_metadata(cx: &CrateContext,
                 ty::vstore_fixed(len) => {
                     fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
                 }
-                ty::vstore_uniq if ty::type_contents(cx.tcx, mt.ty).owns_managed() => {
-                    let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, usage_site_span);
-                    pointer_type_metadata(cx, t, boxed_vec_metadata)
-                }
                 ty::vstore_uniq => {
                     let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
                     pointer_type_metadata(cx, t, vec_metadata)
@@ -2164,12 +2160,11 @@ fn create_pointer_to_box_metadata(cx: &CrateContext,
                 }
             }
         },
-        ty::ty_uniq(ref mt) if ty::type_contents(cx.tcx, mt.ty).owns_managed() => {
-            create_pointer_to_box_metadata(cx, t, mt.ty)
-        },
-        ty::ty_uniq(ref mt)    |
-        ty::ty_ptr(ref mt)     |
-        ty::ty_rptr(_, ref mt) => {
+        ty::ty_uniq(typ) => {
+            let pointee = type_metadata(cx, typ, usage_site_span);
+            pointer_type_metadata(cx, t, pointee)
+        }
+        ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
             let pointee = type_metadata(cx, mt.ty, usage_site_span);
             pointer_type_metadata(cx, t, pointee)
         },
@@ -2193,7 +2188,7 @@ fn create_pointer_to_box_metadata(cx: &CrateContext,
 
     let mut created_types = debug_context(cx).created_types.borrow_mut();
     created_types.get().insert(cache_id, type_metadata);
-    return type_metadata;
+    type_metadata
 }
 
 #[deriving(Eq)]
diff --git a/src/librustc/middle/trans/doc.rs b/src/librustc/middle/trans/doc.rs
new file mode 100644 (file)
index 0000000..b44f2ba
--- /dev/null
@@ -0,0 +1,237 @@
+// 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.
+
+/*!
+
+# Documentation for the trans module
+
+This module contains high-level summaries of how the various modules
+in trans work. It is a work in progress. For detailed comments,
+naturally, you can refer to the individual modules themselves.
+
+## The Expr module
+
+The expr module handles translation of expressions. The most general
+translation routine is `trans()`, which will translate an expression
+into a datum. `trans_into()` is also available, which will translate
+an expression and write the result directly into memory, sometimes
+avoiding the need for a temporary stack slot. Finally,
+`trans_to_lvalue()` is available if you'd like to ensure that the
+result has cleanup scheduled.
+
+Internally, each of these functions dispatches to various other
+expression functions depending on the kind of expression. We divide
+up expressions into:
+
+- **Datum expressions:** Those that most naturally yield values.
+  Examples would be `22`, `~x`, or `a + b` (when not overloaded).
+- **DPS expressions:** Those that most naturally write into a location
+  in memory. Examples would be `foo()` or `Point { x: 3, y: 4 }`.
+- **Statement expressions:** That that do not generate a meaningful
+  result. Examples would be `while { ... }` or `return 44`.
+
+## The Datum module
+
+A `Datum` encapsulates the result of evaluating a Rust expression.  It
+contains a `ValueRef` indicating the result, a `ty::t` describing the
+the Rust type, but also a *kind*. The kind indicates whether the datum
+has cleanup scheduled (lvalue) or not (rvalue) and -- in the case of
+rvalues -- whether or not the value is "by ref" or "by value".
+
+The datum API is designed to try and help you avoid memory errors like
+forgetting to arrange cleanup or duplicating a value. The type of the
+datum incorporates the kind, and thus reflects whether it has cleanup
+scheduled:
+
+- `Datum<Lvalue>` -- by ref, cleanup scheduled
+- `Datum<Rvalue>` -- by value or by ref, no cleanup scheduled
+- `Datum<Expr>` -- either `Datum<Lvalue>` or `Datum<Rvalue>`
+
+Rvalue and expr datums are noncopyable, and most of the methods on
+datums consume the datum itself (with some notable exceptions). This
+reflects the fact that datums may represent affine values which ought
+to be consumed exactly once, and if you were to try to (for example)
+store an affine value multiple times, you would be duplicating it,
+which would certainly be a bug.
+
+Some of the datum methods, however, are designed to work only on
+copyable values such as ints or pointers. Those methods may borrow the
+datum (`&self`) rather than consume it, but they always include
+assertions on the type of the value represented to check that this
+makes sense. An example is `shallow_copy_and_take()`, which duplicates
+a datum value.
+
+Translating an expression always yields a `Datum<Expr>` result, but
+the methods `to_[lr]value_datum()` can be used to coerce a
+`Datum<Expr>` into a `Datum<Lvalue>` or `Datum<Rvalue>` as
+needed. Coercing to an lvalue is fairly common, and generally occurs
+whenever it is necessary to inspect a value and pull out its
+subcomponents (for example, a match, or indexing expression). Coercing
+to an rvalue is more unusual; it occurs when moving values from place
+to place, such as in an assignment expression or parameter passing.
+
+### Lvalues in detail
+
+An lvalue datum is one for which cleanup has been scheduled. Lvalue
+datums are always located in memory, and thus the `ValueRef` for an
+LLVM value is always a pointer to the actual Rust value. This means
+that if the Datum has a Rust type of `int`, then the LLVM type of the
+`ValueRef` will be `int*` (pointer to int).
+
+Because lvalues already have cleanups scheduled, the memory must be
+zeroed to prevent the cleanup from taking place (presuming that the
+Rust type needs drop in the first place, otherwise it doesn't
+matter). The Datum code automatically performs this zeroing when the
+value is stored to a new location, for example.
+
+Lvalues usually result from evaluating lvalue expressions. For
+example, evaluating a local variable `x` yields an lvalue, as does a
+reference to a field like `x.f` or an index `x[i]`.
+
+Lvalue datums can also arise by *converting* an rvalue into an lvalue.
+This is done with the `to_lvalue_datum` method defined on
+`Datum<Expr>`. Basically this method just schedules cleanup if the
+datum is an rvalue, possibly storing the value into a stack slot first
+if needed. Converting rvalues into lvalues occurs in constructs like
+`&foo()` or `match foo() { ref x => ... }`, where the user is
+implicitly requesting a temporary.
+
+Somewhat surprisingly, not all lvalue expressions yield lvalue datums
+when trans'd. Ultimately the reason for this is to micro-optimize
+the resulting LLVM. For example, consider the following code:
+
+    fn foo() -> ~int { ... }
+    let x = *foo();
+
+The expression `*foo()` is an lvalue, but if you invoke `expr::trans`,
+it will return an rvalue datum. See `deref_once` in expr.rs for
+more details.
+
+### Rvalues in detail
+
+Rvalues datums are values with no cleanup scheduled. One must be
+careful with rvalue datums to ensure that cleanup is properly
+arranged, usually by converting to an lvalue datum or by invoking the
+`add_clean` method.
+
+### Scratch datums
+
+Sometimes you need some temporary scratch space.  The functions
+`[lr]value_scratch_datum()` can be used to get temporary stack
+space. As their name suggests, they yield lvalues and rvalues
+respectively. That is, the slot from `lvalue_scratch_datum` will have
+cleanup arranged, and the slot from `rvalue_scratch_datum` does not.
+
+## The Cleanup module
+
+The cleanup module tracks what values need to be cleaned up as scopes
+are exited, either via failure or just normal control flow. The basic
+idea is that the function context maintains a stack of cleanup scopes
+that are pushed/popped as we traverse the AST tree. There is typically
+at least one cleanup scope per AST node; some AST nodes may introduce
+additional temporary scopes.
+
+Cleanup items can be scheduled into any of the scopes on the stack.
+Typically, when a scope is popped, we will also generate the code for
+each of its cleanups at that time. This corresponds to a normal exit
+from a block (for example, an expression completing evaluation
+successfully without failure). However, it is also possible to pop a
+block *without* executing its cleanups; this is typically used to
+guard intermediate values that must be cleaned up on failure, but not
+if everything goes right. See the section on custom scopes below for
+more details.
+
+Cleanup scopes come in three kinds:
+- **AST scopes:** each AST node in a function body has a corresponding
+  AST scope. We push the AST scope when we start generate code for an AST
+  node and pop it once the AST node has been fully generated.
+- **Loop scopes:** loops have an additional cleanup scope. Cleanups are
+  never scheduled into loop scopes; instead, they are used to record the
+  basic blocks that we should branch to when a `continue` or `break` statement
+  is encountered.
+- **Custom scopes:** custom scopes are typically used to ensure cleanup
+  of intermediate values.
+
+### When to schedule cleanup
+
+Although the cleanup system is intended to *feel* fairly declarative,
+it's still important to time calls to `schedule_clean()` correctly.
+Basically, you should not schedule cleanup for memory until it has
+been initialized, because if an unwind should occur before the memory
+is fully initialized, then the cleanup will run and try to free or
+drop uninitialized memory. If the initialization itself produces
+byproducts that need to be freed, then you should use temporary custom
+scopes to ensure that those byproducts will get freed on unwind.  For
+example, an expression like `~foo()` will first allocate a box in the
+heap and then call `foo()` -- if `foo()` should fail, this box needs
+to be *shallowly* freed.
+
+### Long-distance jumps
+
+In addition to popping a scope, which corresponds to normal control
+flow exiting the scope, we may also *jump out* of a scope into some
+earlier scope on the stack. This can occur in response to a `return`,
+`break`, or `continue` statement, but also in response to failure. In
+any of these cases, we will generate a series of cleanup blocks for
+each of the scopes that is exited. So, if the stack contains scopes A
+... Z, and we break out of a loop whose corresponding cleanup scope is
+X, we would generate cleanup blocks for the cleanups in X, Y, and Z.
+After cleanup is done we would branch to the exit point for scope X.
+But if failure should occur, we would generate cleanups for all the
+scopes from A to Z and then resume the unwind process afterwards.
+
+To avoid generating tons of code, we cache the cleanup blocks that we
+create for breaks, returns, unwinds, and other jumps. Whenever a new
+cleanup is scheduled, though, we must clear these cached blocks. A
+possible improvement would be to keep the cached blocks but simply
+generate a new block which performs the additional cleanup and then
+branches to the existing cached blocks.
+
+### AST and loop cleanup scopes
+
+AST cleanup scopes are pushed when we begin and end processing an AST
+node. They are used to house cleanups related to rvalue temporary that
+get referenced (e.g., due to an expression like `&Foo()`). Whenever an
+AST scope is popped, we always trans all the cleanups, adding the cleanup
+code after the postdominator of the AST node.
+
+AST nodes that represent breakable loops also push a loop scope; the
+loop scope never has any actual cleanups, it's just used to point to
+the basic blocks where control should flow after a "continue" or
+"break" statement. Popping a loop scope never generates code.
+
+### Custom cleanup scopes
+
+Custom cleanup scopes are used for a variety of purposes. The most
+common though is to handle temporary byproducts, where cleanup only
+needs to occur on failure. The general strategy is to push a custom
+cleanup scope, schedule *shallow* cleanups into the custom scope, and
+then pop the custom scope (without transing the cleanups) when
+execution succeeds normally. This way the cleanups are only trans'd on
+unwind, and only up until the point where execution succeeded, at
+which time the complete value should be stored in an lvalue or some
+other place where normal cleanup applies.
+
+To spell it out, here is an example. Imagine an expression `~expr`.
+We would basically:
+
+1. Push a custom cleanup scope C.
+2. Allocate the `~` box.
+3. Schedule a shallow free in the scope C.
+4. Trans `expr` into the box.
+5. Pop the scope C.
+6. Return the box as an rvalue.
+
+This way, if a failure occurs while transing `expr`, the custom
+cleanup scope C is pushed and hence the box will be freed. The trans
+code for `expr` itself is responsible for freeing any other byproducts
+that may be in play.
+
+*/
index 8d3b953af1829898664d80cdf9597150f2215be6..36fc927b64c4546ba91468b8e82acab05d648404 100644 (file)
 // except according to those terms.
 
 /*!
-
-# Translation of expressions.
-
-## Recommended entry point
-
-If you wish to translate an expression, the preferred way to do
-so is to use:
-
-    expr::trans_into(block, expr, Dest) -> block
-
-This will generate code that evaluates `expr`, storing the result into
-`Dest`, which must either be the special flag ignore (throw the result
-away) or be a pointer to memory of the same type/size as the
-expression.  It returns the resulting basic block.  This form will
-handle all automatic adjustments for you. The value will be moved if
-its type is linear and copied otherwise.
-
-## Translation to a datum
-
-In some cases, `trans_into()` is too narrow of an interface.
-Generally this occurs either when you know that the result value is
-going to be a scalar, or when you need to evaluate the expression into
-some memory location so you can go and inspect it (e.g., assignments,
-`match` expressions, the `&` operator).
-
-In such cases, you want the following function:
-
-    trans_to_datum(block, expr) -> DatumBlock
-
-This function generates code to evaluate the expression and return a
-`Datum` describing where the result is to be found.  This function
-tries to return its result in the most efficient way possible, without
-introducing extra copies or sacrificing information.  Therefore, for
-lvalue expressions, you always get a by-ref `Datum` in return that
-points at the memory for this lvalue.  For rvalue expressions, we will
-return a by-value `Datum` whenever possible, but it is often necessary
-to allocate a stack slot, store the result of the rvalue in there, and
-then return a pointer to the slot (see the discussion later on about
-the different kinds of rvalues).
-
-NB: The `trans_to_datum()` function does perform adjustments, but
-since it returns a pointer to the value "in place" it does not handle
-moves.  If you wish to copy/move the value returned into a new
-location, you should use the Datum method `store_to()` (move or copy
-depending on type). You can also use `move_to()` (force move) or
-`copy_to()` (force copy) for special situations.
-
-## Translating local variables
-
-`trans_local_var()` can be used to trans a ref to a local variable
-that is not an expression.  This is needed for captures.
-
-## Ownership and cleanups
-
-The current system for cleanups associates required cleanups with
-block contexts.  Block contexts are structured into a tree that
-resembles the code itself.  Not every block context has cleanups
-associated with it, only those blocks that have a kind of
-`block_scope`.  See `common::block_kind` for more details.
-
-If you invoke `trans_into()`, no cleanup is scheduled for you.  The
-value is written into the given destination and is assumed to be owned
-by that destination.
-
-When you invoke `trans_to_datum()` on an rvalue, the resulting
-datum/value will have an appropriate cleanup scheduled for the
-innermost cleanup scope.  If you later use `move_to()` or
-`drop_val()`, this cleanup will be canceled.
-
-During the evaluation of an expression, temporary cleanups are created
-and later canceled.  These represent intermediate or partial results
-which must be cleaned up in the event of task failure.
-
-## Implementation details
-
-We divide expressions into three categories, based on how they are most
-naturally implemented:
-
-1. Lvalues
-2. Datum rvalues
-3. DPS rvalues
-4. Statement rvalues
-
-Lvalues always refer to user-assignable memory locations.
-Translating those always results in a by-ref datum; this introduces
-no inefficiencies into the generated code, because all lvalues are
-naturally addressable.
-
-Datum rvalues are rvalues that always generate datums as a result.
-These are generally scalar results, such as `a+b` where `a` and `b`
-are integers.
-
-DPS rvalues are rvalues that, when translated, must be given a
-memory location to write into (or the Ignore flag).  These are
-generally expressions that produce structural results that are
-larger than one word (e.g., a struct literal), but also expressions
-(like `if`) that involve control flow (otherwise we'd have to
-generate phi nodes).
-
-Finally, statement rvalues are rvalues that always produce a nil
-return type, such as `while` loops or assignments (`a = b`).
-
-*/
-
+ * # Translation of Expressions
+ *
+ * Public entry points:
+ *
+ * - `trans_into(bcx, expr, dest) -> bcx`: evaluates an expression,
+ *   storing the result into `dest`. This is the preferred form, if you
+ *   can manage it.
+ *
+ * - `trans(bcx, expr) -> DatumBlock`: evaluates an expression, yielding
+ *   `Datum` with the result. You can then store the datum, inspect
+ *   the value, etc. This may introduce temporaries if the datum is a
+ *   structural type.
+ *
+ * - `trans_to_lvalue(bcx, expr, "...") -> DatumBlock`: evaluates an
+ *   expression and ensures that the result has a cleanup associated with it,
+ *   creating a temporary stack slot if necessary.
+ *
+ * - `trans_local_var -> Datum`: looks up a local variable or upvar.
+ *
+ * See doc.rs for more comments.
+ */
 
 use back::abi;
 use back::link;
 use middle::trans::build::*;
 use middle::trans::callee::DoAutorefArg;
 use middle::trans::callee;
+use middle::trans::cleanup;
+use middle::trans::cleanup::CleanupMethods;
 use middle::trans::closure;
 use middle::trans::common::*;
 use middle::trans::consts;
 use middle::trans::controlflow;
 use middle::trans::datum::*;
 use middle::trans::debuginfo;
+use middle::trans::glue;
 use middle::trans::machine;
 use middle::trans::meth;
 use middle::trans::inline;
 use middle::trans::tvec;
 use middle::trans::type_of;
+use middle::trans::write_guard;
 use middle::ty::struct_fields;
 use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoObject, AutoUnsafe};
 use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn};
@@ -175,31 +96,102 @@ pub fn to_str(&self, ccx: &CrateContext) -> ~str {
     }
 }
 
-pub fn trans_to_datum<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
-                      -> DatumBlock<'a> {
-    debug!("trans_to_datum(expr={})", bcx.expr_to_str(expr));
+pub fn trans_into<'a>(bcx: &'a Block<'a>,
+                      expr: &ast::Expr,
+                      dest: Dest)
+                      -> &'a Block<'a> {
+    /*!
+     * This function is equivalent to `trans(bcx, expr).store_to_dest(dest)`
+     * but it may generate better optimized LLVM code.
+     */
+
+    let mut bcx = bcx;
+
+    let is_adjusted = {
+        let adjustments = bcx.tcx().adjustments.borrow();
+        adjustments.get().contains_key(&expr.id)
+    };
+
+    if is_adjusted {
+        // use trans, which may be less efficient but
+        // which will perform the adjustments:
+        let datum = unpack_datum!(bcx, trans(bcx, expr));
+        return datum.store_to_dest(bcx, dest, expr.id)
+    }
+
+    debug!("trans_into() expr={}", expr.repr(bcx.tcx()));
+    debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
+
+    bcx.fcx.push_ast_cleanup_scope(expr.id);
+
+    let kind = ty::expr_kind(bcx.tcx(), bcx.ccx().maps.method_map, expr);
+    bcx = match kind {
+        ty::LvalueExpr | ty::RvalueDatumExpr => {
+            trans_unadjusted(bcx, expr).store_to_dest(dest, expr.id)
+        }
+        ty::RvalueDpsExpr => {
+            trans_rvalue_dps_unadjusted(bcx, expr, dest)
+        }
+        ty::RvalueStmtExpr => {
+            trans_rvalue_stmt_unadjusted(bcx, expr)
+        }
+    };
+
+    bcx.fcx.pop_and_trans_ast_cleanup_scope(bcx, expr.id)
+}
+
+pub fn trans<'a>(bcx: &'a Block<'a>,
+                 expr: &ast::Expr)
+                 -> DatumBlock<'a, Expr> {
+    /*!
+     * Translates an expression, returning a datum (and new block)
+     * encapsulating the result. When possible, it is preferred to
+     * use `trans_into`, as that may avoid creating a temporary on
+     * the stack.
+     */
+
+    debug!("trans(expr={})", bcx.expr_to_str(expr));
 
     let mut bcx = bcx;
-    let mut datum = unpack_datum!(bcx, trans_to_datum_unadjusted(bcx, expr));
+    let fcx = bcx.fcx;
+
+    fcx.push_ast_cleanup_scope(expr.id);
+    let datum = unpack_datum!(bcx, trans_unadjusted(bcx, expr));
+    let datum = unpack_datum!(bcx, apply_adjustments(bcx, expr, datum));
+    bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, expr.id);
+    return DatumBlock(bcx, datum);
+}
+
+fn apply_adjustments<'a>(bcx: &'a Block<'a>,
+                         expr: &ast::Expr,
+                         datum: Datum<Expr>)
+                         -> DatumBlock<'a, Expr> {
+    /*!
+     * Helper for trans that apply adjustments from `expr` to `datum`,
+     * which should be the unadjusted translation of `expr`.
+     */
+
+    let mut bcx = bcx;
+    let mut datum = datum;
     let adjustment = {
         let adjustments = bcx.tcx().adjustments.borrow();
         match adjustments.get().find_copy(&expr.id) {
-            None => { return DatumBlock {bcx: bcx, datum: datum}; }
+            None => {
+                return DatumBlock(bcx, datum);
+            }
             Some(adj) => { adj }
         }
     };
-    debug!("unadjusted datum: {}", datum.to_str(bcx.ccx()));
+    debug!("unadjusted datum for expr {}: {}",
+           expr.id, datum.to_str(bcx.ccx()));
     match *adjustment {
         AutoAddEnv(..) => {
             datum = unpack_datum!(bcx, add_env(bcx, expr, datum));
         }
         AutoDerefRef(ref adj) => {
             if adj.autoderefs > 0 {
-                datum =
-                    unpack_datum!(
-                        bcx,
-                        datum.autoderef(bcx, expr.span,
-                                        expr.id, adj.autoderefs));
+                datum = unpack_datum!(
+                    bcx, deref_multiple(bcx, expr, datum, adj.autoderefs));
             }
 
             datum = match adj.autoref {
@@ -208,7 +200,7 @@ pub fn trans_to_datum<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
                 }
                 Some(AutoUnsafe(..)) | // region + unsafe ptrs have same repr
                 Some(AutoPtr(..)) => {
-                    unpack_datum!(bcx, auto_ref(bcx, datum))
+                    unpack_datum!(bcx, auto_ref(bcx, datum, expr))
                 }
                 Some(AutoBorrowVec(..)) => {
                     unpack_datum!(bcx, auto_slice(bcx, adj.autoderefs,
@@ -230,51 +222,75 @@ pub fn trans_to_datum<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
             };
         }
         AutoObject(..) => {
-
             let adjusted_ty = ty::expr_ty_adjusted(bcx.tcx(), expr);
-            let scratch = scratch_datum(bcx, adjusted_ty, "__adjust", false);
-
-            bcx = meth::trans_trait_cast(bcx, expr, expr.id, SaveIn(scratch.val), Some(datum));
-
-            datum = scratch.to_appropriate_datum(bcx);
-            datum.add_clean(bcx);
+            let scratch = rvalue_scratch_datum(bcx, adjusted_ty, "__adjust");
+            bcx = meth::trans_trait_cast(
+                bcx, datum, expr.id, SaveIn(scratch.val));
+            datum = scratch.to_expr_datum();
         }
     }
     debug!("after adjustments, datum={}", datum.to_str(bcx.ccx()));
     return DatumBlock {bcx: bcx, datum: datum};
 
-    fn auto_ref<'a>(bcx: &'a Block<'a>, datum: Datum) -> DatumBlock<'a> {
-        DatumBlock {bcx: bcx, datum: datum.to_rptr(bcx)}
+    fn auto_ref<'a>(bcx: &'a Block<'a>,
+                    datum: Datum<Expr>,
+                    expr: &ast::Expr)
+                    -> DatumBlock<'a, Expr> {
+        let mut bcx = bcx;
+
+        // Ensure cleanup of `datum` if not already scheduled and obtain
+        // a "by ref" pointer.
+        let lv_datum = unpack_datum!(bcx, datum.to_lvalue_datum(bcx, "autoref", expr.id));
+
+        // Compute final type. Note that we are loose with the region and
+        // mutability, since those things don't matter in trans.
+        let referent_ty = lv_datum.ty;
+        let ptr_ty = ty::mk_imm_rptr(bcx.tcx(), ty::ReStatic, referent_ty);
+
+        // Get the pointer.
+        let llref = lv_datum.to_llref();
+
+        // Construct the resulting datum, using what was the "by ref"
+        // ValueRef of type `referent_ty` to be the "by value" ValueRef
+        // of type `&referent_ty`.
+        DatumBlock(bcx, Datum(llref, ptr_ty, RvalueExpr(Rvalue(ByValue))))
     }
 
     fn auto_borrow_fn<'a>(
                       bcx: &'a Block<'a>,
                       adjusted_ty: ty::t,
-                      datum: Datum)
-                      -> DatumBlock<'a> {
+                      datum: Datum<Expr>)
+                      -> DatumBlock<'a, Expr> {
         // Currently, all closure types are represented precisely the
         // same, so no runtime adjustment is required, but we still
         // must patchup the type.
         DatumBlock {bcx: bcx,
-                    datum: Datum {val: datum.val, ty: adjusted_ty,
-                                  mode: datum.mode}}
+                    datum: Datum {val: datum.val,
+                                  ty: adjusted_ty,
+                                  kind: datum.kind}}
     }
 
     fn auto_slice<'a>(
                   bcx: &'a Block<'a>,
                   autoderefs: uint,
                   expr: &ast::Expr,
-                  datum: Datum)
-                  -> DatumBlock<'a> {
+                  datum: Datum<Expr>)
+                  -> DatumBlock<'a, Expr> {
         // This is not the most efficient thing possible; since slices
         // are two words it'd be better if this were compiled in
         // 'dest' mode, but I can't find a nice way to structure the
         // code and keep it DRY that accommodates that use case at the
         // moment.
 
+        let mut bcx = bcx;
         let tcx = bcx.tcx();
         let unit_ty = ty::sequence_element_type(tcx, datum.ty);
 
+        // Arrange cleanup, if not already done. This is needed in
+        // case we are auto-slicing an owned vector or some such.
+        let datum = unpack_datum!(
+            bcx, datum.to_lvalue_datum(bcx, "auto_slice", expr.id));
+
         let (bcx, base, len) =
             datum.get_vec_base_and_len(bcx, expr.span, expr.id, autoderefs+1);
 
@@ -284,15 +300,16 @@ fn auto_slice<'a>(
                                   ty::mt { ty: unit_ty, mutbl: ast::MutImmutable },
                                   ty::vstore_slice(ty::ReStatic));
 
-        let scratch = scratch_datum(bcx, slice_ty, "__adjust", false);
-
+        let scratch = rvalue_scratch_datum(bcx, slice_ty, "__adjust");
         Store(bcx, base, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
         Store(bcx, len, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
-        DatumBlock {bcx: bcx, datum: scratch}
+        DatumBlock(bcx, scratch.to_expr_datum())
     }
 
-    fn add_env<'a>(bcx: &'a Block<'a>, expr: &ast::Expr, datum: Datum)
-               -> DatumBlock<'a> {
+    fn add_env<'a>(bcx: &'a Block<'a>,
+                   expr: &ast::Expr,
+                   datum: Datum<Expr>)
+                   -> DatumBlock<'a, Expr> {
         // This is not the most efficient thing possible; since closures
         // are two words it'd be better if this were compiled in
         // 'dest' mode, but I can't find a nice way to structure the
@@ -302,31 +319,31 @@ fn add_env<'a>(bcx: &'a Block<'a>, expr: &ast::Expr, datum: Datum)
         let tcx = bcx.tcx();
         let closure_ty = expr_ty_adjusted(bcx, expr);
         debug!("add_env(closure_ty={})", closure_ty.repr(tcx));
-        let scratch = scratch_datum(bcx, closure_ty, "__adjust", false);
+        let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust");
         let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
-        assert_eq!(datum.appropriate_mode(bcx.ccx()), ByValue);
-        Store(bcx, datum.to_appropriate_llval(bcx), llfn);
+        let llval = datum.to_llscalarish(bcx);
+        Store(bcx, llval, llfn);
         let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]);
         Store(bcx, base::null_env_ptr(bcx.ccx()), llenv);
-        DatumBlock {bcx: bcx, datum: scratch}
+        DatumBlock(bcx, scratch.to_expr_datum())
     }
 
     fn auto_slice_and_ref<'a>(
                           bcx: &'a Block<'a>,
                           autoderefs: uint,
                           expr: &ast::Expr,
-                          datum: Datum)
-                          -> DatumBlock<'a> {
+                          datum: Datum<Expr>)
+                          -> DatumBlock<'a, Expr> {
         let DatumBlock { bcx, datum } = auto_slice(bcx, autoderefs, expr, datum);
-        auto_ref(bcx, datum)
+        auto_ref(bcx, datum, expr)
     }
 
     fn auto_borrow_obj<'a>(
                        mut bcx: &'a Block<'a>,
                        autoderefs: uint,
                        expr: &ast::Expr,
-                       source_datum: Datum)
-                       -> DatumBlock<'a> {
+                       source_datum: Datum<Expr>)
+                       -> DatumBlock<'a, Expr> {
         let tcx = bcx.tcx();
         let target_obj_ty = expr_ty_adjusted(bcx, expr);
         debug!("auto_borrow_obj(target={})",
@@ -343,7 +360,8 @@ fn auto_borrow_obj<'a>(
             }
         };
 
-        // check if any borrowing is really needed or we could reuse the source_datum instead
+        // check if any borrowing is really needed or we could reuse
+        // the source_datum instead
         match ty::get(target_obj_ty).sty {
             ty::ty_trait(_, _, ty::RegionTraitStore(target_scope), target_mutbl, _) => {
                 if target_mutbl == ast::MutImmutable && target_mutbl == source_mutbl {
@@ -361,14 +379,16 @@ fn auto_borrow_obj<'a>(
             _ => {}
         }
 
-        let scratch = scratch_datum(bcx, target_obj_ty,
-                                    "__auto_borrow_obj", false);
+        let scratch = rvalue_scratch_datum(bcx, target_obj_ty,
+                                           "__auto_borrow_obj");
 
         // Convert a @Object, ~Object, or &Object pair into an &Object pair.
 
         // Get a pointer to the source object, which is represented as
         // a (vtable, data) pair.
-        let source_llval = source_datum.to_ref_llval(bcx);
+        let source_datum = unpack_datum!(
+            bcx, source_datum.to_lvalue_datum(bcx, "auto_borrow_obj", expr.id));
+        let source_llval = source_datum.to_llref();
 
         // Set the vtable field of the new pair
         let vtable_ptr = GEPi(bcx, source_llval, [0u, abi::trt_field_vtable]);
@@ -378,194 +398,87 @@ fn auto_borrow_obj<'a>(
         // Load the data for the source, which is either an @T,
         // ~T, or &T, depending on source_obj_ty.
         let source_data_ptr = GEPi(bcx, source_llval, [0u, abi::trt_field_box]);
-        let source_data = Load(bcx, source_data_ptr); // always a ptr
         let target_data = match source_store {
             ty::BoxTraitStore(..) => {
-                // For deref of @T, create a dummy datum and use the datum's
-                // deref method. This is more work than just calling GEPi
-                // ourselves. Note that we don't know the type T, so
-                // just substitute `i8`-- it doesn't really matter for
-                // our purposes right now.
+                // For deref of @T, create a dummy datum and use the
+                // datum's deref method. This is more work than just
+                // calling GEPi ourselves, but it ensures that any
+                // necessary rooting is performed. Note that we don't
+                // know the type T, so just substitute `i8`-- it
+                // doesn't really matter for our purposes right now.
                 let source_ty = ty::mk_box(tcx, ty::mk_i8());
-                let source_datum =
-                    Datum {val: source_data,
-                           ty: source_ty,
-                           mode: ByValue};
-                let derefd_datum =
-                    unpack_datum!(bcx,
-                                  source_datum.deref(bcx,
-                                                     expr,
-                                                     autoderefs));
-                derefd_datum.to_rptr(bcx).to_value_llval(bcx)
-            }
-            ty::UniqTraitStore(..) => {
-                // For a ~T box, there may or may not be a header,
-                // depending on whether the type T references managed
-                // boxes. However, since we do not *know* the type T
-                // for objects, this presents a hurdle. Our solution is
-                // to load the "borrow offset" from the type descriptor;
-                // this value will either be 0 or sizeof(BoxHeader), depending
-                // on the type T.
-                let llopaque =
-                    PointerCast(bcx, source_data, Type::opaque().ptr_to());
-                let lltydesc_ptr_ptr =
-                    PointerCast(bcx, vtable,
-                                bcx.ccx().tydesc_type.ptr_to().ptr_to());
-                let lltydesc_ptr =
-                    Load(bcx, lltydesc_ptr_ptr);
-                let borrow_offset_ptr =
-                    GEPi(bcx, lltydesc_ptr,
-                         [0, abi::tydesc_field_borrow_offset]);
-                let borrow_offset =
-                    Load(bcx, borrow_offset_ptr);
-                InBoundsGEP(bcx, llopaque, [borrow_offset])
+                let source_datum = Datum(source_data_ptr, source_ty, LvalueExpr);
+                let derefd_datum = unpack_datum!(
+                    bcx, deref_once(bcx, expr, source_datum, autoderefs));
+                derefd_datum.assert_lvalue(bcx).to_llref()
             }
-            ty::RegionTraitStore(..) => {
-                source_data
+            ty::UniqTraitStore(..) | ty::RegionTraitStore(..) => {
+                Load(bcx, source_data_ptr)
             }
         };
         Store(bcx, target_data,
               GEPi(bcx, scratch.val, [0u, abi::trt_field_box]));
 
-        DatumBlock { bcx: bcx, datum: scratch }
+        DatumBlock(bcx, scratch.to_expr_datum())
     }
 }
 
-pub fn trans_into<'a>(bcx: &'a Block<'a>, expr: &ast::Expr, dest: Dest)
-                  -> &'a Block<'a> {
-    let adjustment_found = {
-        let adjustments = bcx.tcx().adjustments.borrow();
-        adjustments.get().contains_key(&expr.id)
-    };
-    if adjustment_found {
-        // use trans_to_datum, which is mildly less efficient but
-        // which will perform the adjustments:
-        let datumblock = trans_to_datum(bcx, expr);
-        return match dest {
-            Ignore => datumblock.bcx,
-            SaveIn(lldest) => datumblock.store_to(INIT, lldest)
-        };
-    }
-
-    trans_into_unadjusted(bcx, expr, dest)
-}
-
-pub fn trans_into_unadjusted<'a>(
-                             bcx: &'a Block<'a>,
-                             expr: &ast::Expr,
-                             dest: Dest)
-                             -> &'a Block<'a> {
-    let ty = expr_ty(bcx, expr);
-
-    debug!("trans_into_unadjusted(expr={}, dest={})",
-           bcx.expr_to_str(expr),
-           dest.to_str(bcx.ccx()));
-    let _indenter = indenter();
-
-    debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
-
-    let dest = {
-        if ty::type_is_voidish(bcx.tcx(), ty) {
-            Ignore
-        } else {
-            dest
-        }
-    };
-
-    let kind = bcx.expr_kind(expr);
-    debug!("expr kind = {:?}", kind);
-    return match kind {
-        ty::LvalueExpr => {
-            let datumblock = trans_lvalue_unadjusted(bcx, expr);
-            match dest {
-                Ignore => datumblock.bcx,
-                SaveIn(lldest) => datumblock.store_to(INIT, lldest)
-            }
-        }
-        ty::RvalueDatumExpr => {
-            let datumblock = trans_rvalue_datum_unadjusted(bcx, expr);
-            match dest {
-                Ignore => datumblock.drop_val(),
-
-                // When processing an rvalue, the value will be newly
-                // allocated, so we always `move_to` so as not to
-                // unnecessarily inc ref counts and so forth:
-                SaveIn(lldest) => datumblock.move_to(INIT, lldest)
-            }
-        }
-        ty::RvalueDpsExpr => {
-            trans_rvalue_dps_unadjusted(bcx, expr, dest)
-        }
-        ty::RvalueStmtExpr => {
-            trans_rvalue_stmt_unadjusted(bcx, expr)
-        }
-    };
-}
-
-fn trans_lvalue<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> DatumBlock<'a> {
+pub fn trans_to_lvalue<'a>(bcx: &'a Block<'a>,
+                           expr: &ast::Expr,
+                           name: &str)
+                           -> DatumBlock<'a, Lvalue> {
     /*!
+     * Translates an expression in "lvalue" mode -- meaning that it
+     * returns a reference to the memory that the expr represents.
+     *
+     * If this expression is an rvalue, this implies introducing a
+     * temporary.  In other words, something like `x().f` is
+     * translated into roughly the equivalent of
      *
-     * Translates an lvalue expression, always yielding a by-ref
-     * datum.  Generally speaking you should call trans_to_datum()
-     * instead, but sometimes we call trans_lvalue() directly as a
-     * means of asserting that a particular expression is an lvalue. */
+     *   { tmp = x(); tmp.f }
+     */
 
-    let adjustment_opt = {
-        let adjustments = bcx.tcx().adjustments.borrow();
-        adjustments.get().find_copy(&expr.id)
-    };
-    match adjustment_opt {
-        None => trans_lvalue_unadjusted(bcx, expr),
-        Some(_) => {
-            bcx.sess().span_bug(
-                expr.span,
-                format!("trans_lvalue() called on an expression \
-                      with adjustments"));
-        }
-    }
+    let mut bcx = bcx;
+    let datum = unpack_datum!(bcx, trans(bcx, expr));
+    return datum.to_lvalue_datum(bcx, name, expr.id);
 }
 
-fn trans_to_datum_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
-                             -> DatumBlock<'a> {
+fn trans_unadjusted<'a>(bcx: &'a Block<'a>,
+                        expr: &ast::Expr)
+                        -> DatumBlock<'a, Expr> {
     /*!
-     * Translates an expression into a datum.  If this expression
-     * is an rvalue, this will result in a temporary value being
-     * created.  If you plan to store the value somewhere else,
-     * you should prefer `trans_into()` instead.
+     * A version of `trans` that ignores adjustments. You almost
+     * certainly do not want to call this directly.
      */
 
     let mut bcx = bcx;
 
-    debug!("trans_to_datum_unadjusted(expr={})", bcx.expr_to_str(expr));
+    debug!("trans_unadjusted(expr={})", bcx.expr_to_str(expr));
     let _indenter = indenter();
 
     debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
 
-    match ty::expr_kind(bcx.tcx(), bcx.ccx().maps.method_map, expr) {
-        ty::LvalueExpr => {
-            return trans_lvalue_unadjusted(bcx, expr);
-        }
-
-        ty::RvalueDatumExpr => {
+    return match ty::expr_kind(bcx.tcx(), bcx.ccx().maps.method_map, expr) {
+        ty::LvalueExpr | ty::RvalueDatumExpr => {
             let datum = unpack_datum!(bcx, {
-                trans_rvalue_datum_unadjusted(bcx, expr)
+                trans_datum_unadjusted(bcx, expr)
             });
-            datum.add_clean(bcx);
-            return DatumBlock {bcx: bcx, datum: datum};
+
+            DatumBlock {bcx: bcx, datum: datum}
         }
 
         ty::RvalueStmtExpr => {
             bcx = trans_rvalue_stmt_unadjusted(bcx, expr);
-            return nil(bcx, expr_ty(bcx, expr));
+            nil(bcx, expr_ty(bcx, expr))
         }
 
         ty::RvalueDpsExpr => {
             let ty = expr_ty(bcx, expr);
-            if ty::type_is_voidish(bcx.tcx(), ty) {
+            if type_is_zero_size(bcx.ccx(), ty) {
                 bcx = trans_rvalue_dps_unadjusted(bcx, expr, Ignore);
-                return nil(bcx, ty);
+                nil(bcx, ty)
             } else {
-                let scratch = scratch_datum(bcx, ty, "", false);
+                let scratch = rvalue_scratch_datum(bcx, ty, "");
                 bcx = trans_rvalue_dps_unadjusted(
                     bcx, expr, SaveIn(scratch.val));
 
@@ -578,50 +491,67 @@ fn trans_to_datum_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
                 // Still, in practice it seems to increase
                 // performance, since we have fewer problems with
                 // morestack churn.
-                let scratch = scratch.to_appropriate_datum(bcx);
+                let scratch = unpack_datum!(
+                    bcx, scratch.to_appropriate_datum(bcx));
 
-                scratch.add_clean(bcx);
-                return DatumBlock {bcx: bcx, datum: scratch};
+                DatumBlock(bcx, scratch.to_expr_datum())
             }
         }
-    }
+    };
 
-    fn nil<'a>(bcx: &'a Block<'a>, ty: ty::t) -> DatumBlock<'a> {
-        let datum = immediate_rvalue(C_nil(), ty);
-        DatumBlock {
-            bcx: bcx,
-            datum: datum,
-        }
+    fn nil<'a>(bcx: &'a Block<'a>, ty: ty::t) -> DatumBlock<'a, Expr> {
+        let llval = C_undef(type_of::type_of(bcx.ccx(), ty));
+        let datum = immediate_rvalue(llval, ty);
+        DatumBlock(bcx, datum.to_expr_datum())
     }
 }
 
-fn trans_rvalue_datum_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
-                                 -> DatumBlock<'a> {
-    let _icx = push_ctxt("trans_rvalue_datum_unadjusted");
+fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
+                              expr: &ast::Expr)
+                              -> DatumBlock<'a, Expr> {
+    let mut bcx = bcx;
+    let fcx = bcx.fcx;
+    let _icx = push_ctxt("trans_datum_unadjusted");
 
     match expr.node {
+        ast::ExprParen(e) => {
+            trans(bcx, e)
+        }
         ast::ExprPath(_) | ast::ExprSelf => {
-            return trans_def_datum_unadjusted(bcx, expr, bcx.def(expr.id));
+            trans_def(bcx, expr, bcx.def(expr.id))
+        }
+        ast::ExprField(base, ident, _) => {
+            trans_rec_field(bcx, base, ident)
+        }
+        ast::ExprIndex(_, base, idx) => {
+            trans_index(bcx, expr, base, idx)
         }
         ast::ExprVstore(contents, ast::ExprVstoreBox) => {
-            return tvec::trans_uniq_or_managed_vstore(bcx, heap_managed,
-                                                      expr, contents);
+            fcx.push_ast_cleanup_scope(contents.id);
+            let datum = unpack_datum!(
+                bcx, tvec::trans_uniq_or_managed_vstore(bcx, heap_managed,
+                                                        expr, contents));
+            bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id);
+            DatumBlock(bcx, datum)
         }
         ast::ExprVstore(contents, ast::ExprVstoreUniq) => {
-            let heap = heap_for_unique(bcx, expr_ty(bcx, contents));
-            return tvec::trans_uniq_or_managed_vstore(bcx, heap,
-                                                      expr, contents);
+            fcx.push_ast_cleanup_scope(contents.id);
+            let datum = unpack_datum!(
+                bcx, tvec::trans_uniq_or_managed_vstore(bcx, heap_exchange,
+                                                        expr, contents));
+            bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id);
+            DatumBlock(bcx, datum)
         }
         ast::ExprBox(_, contents) => {
             // Special case for `~T`. (The other case, for GC, is handled in
             // `trans_rvalue_dps_unadjusted`.)
             let box_ty = expr_ty(bcx, expr);
             let contents_ty = expr_ty(bcx, contents);
-            let heap = heap_for_unique(bcx, contents_ty);
+            let heap = heap_exchange;
             return trans_boxed_expr(bcx, box_ty, contents, contents_ty, heap)
         }
         ast::ExprLit(lit) => {
-            return trans_immediate_lit(bcx, expr, *lit);
+            trans_immediate_lit(bcx, expr, *lit)
         }
         ast::ExprBinary(_, op, lhs, rhs) => {
             // if overloaded, would be RvalueDpsExpr
@@ -630,22 +560,24 @@ fn trans_rvalue_datum_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
                 assert!(!method_map.get().contains_key(&expr.id));
             }
 
-            return trans_binary(bcx, expr, op, lhs, rhs);
+            trans_binary(bcx, expr, op, lhs, rhs)
+        }
+        ast::ExprUnary(_, ast::UnDeref, base) => {
+            let basedatum = unpack_datum!(bcx, trans(bcx, base));
+            deref_once(bcx, expr, basedatum, 0)
         }
         ast::ExprUnary(_, op, x) => {
-            return trans_unary_datum(bcx, expr, op, x);
+            trans_unary_datum(bcx, expr, op, x)
         }
         ast::ExprAddrOf(_, x) => {
-            return trans_addr_of(bcx, expr, x);
+            trans_addr_of(bcx, expr, x)
         }
         ast::ExprCast(val, _) => {
-            return trans_imm_cast(bcx, val, expr.id);
-        }
-        ast::ExprParen(e) => {
-            return trans_rvalue_datum_unadjusted(bcx, e);
+            // Datum output mode means this is a scalar cast:
+            trans_imm_cast(bcx, val, expr.id)
         }
         ast::ExprLogLevel => {
-            return trans_log_level(bcx);
+            trans_log_level(bcx)
         }
         _ => {
             bcx.tcx().sess.span_bug(
@@ -657,8 +589,152 @@ fn trans_rvalue_datum_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
     }
 }
 
-fn trans_rvalue_stmt_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
-                                -> &'a Block<'a> {
+fn trans_rec_field<'a>(bcx: &'a Block<'a>,
+                       base: &ast::Expr,
+                       field: ast::Ident)
+                       -> DatumBlock<'a, Expr> {
+    //! Translates `base.field`.
+
+    let mut bcx = bcx;
+    let _icx = push_ctxt("trans_rec_field");
+
+    let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
+    let repr = adt::represent_type(bcx.ccx(), base_datum.ty);
+    with_field_tys(bcx.tcx(), base_datum.ty, None, |discr, field_tys| {
+            let ix = ty::field_idx_strict(bcx.tcx(), field.name, field_tys);
+            let d = base_datum.get_element(
+                field_tys[ix].mt.ty,
+                |srcval| adt::trans_field_ptr(bcx, repr, srcval, discr, ix));
+            DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
+        })
+}
+
+fn trans_index<'a>(bcx: &'a Block<'a>,
+                   index_expr: &ast::Expr,
+                   base: &ast::Expr,
+                   idx: &ast::Expr)
+                   -> DatumBlock<'a, Expr> {
+    //! Translates `base[idx]`.
+
+    let _icx = push_ctxt("trans_index");
+    let ccx = bcx.ccx();
+    let mut bcx = bcx;
+
+    let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "index"));
+
+    // Translate index expression and cast to a suitable LLVM integer.
+    // Rust is less strict than LLVM in this regard.
+    let ix_datum = unpack_datum!(bcx, trans(bcx, idx));
+    let ix_val = ix_datum.to_llscalarish(bcx);
+    let ix_size = machine::llbitsize_of_real(bcx.ccx(), val_ty(ix_val));
+    let int_size = machine::llbitsize_of_real(bcx.ccx(), ccx.int_type);
+    let ix_val = {
+        if ix_size < int_size {
+            if ty::type_is_signed(expr_ty(bcx, idx)) {
+                SExt(bcx, ix_val, ccx.int_type)
+            } else { ZExt(bcx, ix_val, ccx.int_type) }
+        } else if ix_size > int_size {
+            Trunc(bcx, ix_val, ccx.int_type)
+        } else {
+            ix_val
+        }
+    };
+
+    let vt = tvec::vec_types(bcx, base_datum.ty);
+    base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz");
+
+    let (bcx, base, len) =
+        base_datum.get_vec_base_and_len(bcx, index_expr.span, index_expr.id, 0);
+
+    debug!("trans_index: base {}", bcx.val_to_str(base));
+    debug!("trans_index: len {}", bcx.val_to_str(len));
+
+    let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len);
+    let expect = ccx.intrinsics.get_copy(&("llvm.expect.i1"));
+    let expected = Call(bcx, expect, [bounds_check, C_i1(false)], []);
+    let bcx = with_cond(bcx, expected, |bcx| {
+            controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, len)
+        });
+    let elt = InBoundsGEP(bcx, base, [ix_val]);
+    let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to());
+    DatumBlock(bcx, Datum(elt, vt.unit_ty, LvalueExpr))
+}
+
+fn trans_def<'a>(bcx: &'a Block<'a>,
+                 ref_expr: &ast::Expr,
+                 def: ast::Def)
+                 -> DatumBlock<'a, Expr>
+{
+    //! Translates a reference to a path.
+
+    let _icx = push_ctxt("trans_def_lvalue");
+    match def {
+        ast::DefFn(..) | ast::DefStaticMethod(..) => {
+            trans_def_fn_unadjusted(bcx, ref_expr, def)
+        }
+        ast::DefStatic(did, _) => {
+            let const_ty = expr_ty(bcx, ref_expr);
+
+            fn get_did(ccx: @CrateContext, did: ast::DefId)
+                       -> ast::DefId {
+                if did.crate != ast::LOCAL_CRATE {
+                    inline::maybe_instantiate_inline(ccx, did)
+                } else {
+                    did
+                }
+            }
+
+            fn get_val<'a>(bcx: &'a Block<'a>, did: ast::DefId, const_ty: ty::t)
+                       -> ValueRef {
+                // For external constants, we don't inline.
+                if did.crate == ast::LOCAL_CRATE {
+                    // The LLVM global has the type of its initializer,
+                    // which may not be equal to the enum's type for
+                    // non-C-like enums.
+                    let val = base::get_item_val(bcx.ccx(), did.node);
+                    let pty = type_of::type_of(bcx.ccx(), const_ty).ptr_to();
+                    PointerCast(bcx, val, pty)
+                } else {
+                    {
+                        let extern_const_values = bcx.ccx().extern_const_values.borrow();
+                        match extern_const_values.get().find(&did) {
+                            None => {}  // Continue.
+                            Some(llval) => {
+                                return *llval;
+                            }
+                        }
+                    }
+
+                    unsafe {
+                        let llty = type_of::type_of(bcx.ccx(), const_ty);
+                        let symbol = csearch::get_symbol(
+                            bcx.ccx().sess.cstore,
+                            did);
+                        let llval = symbol.with_c_str(|buf| {
+                                llvm::LLVMAddGlobal(bcx.ccx().llmod,
+                                                    llty.to_ref(),
+                                                    buf)
+                            });
+                        let mut extern_const_values = bcx.ccx().extern_const_values.borrow_mut();
+                        extern_const_values.get().insert(did, llval);
+                        llval
+                    }
+                }
+            }
+
+            let did = get_did(bcx.ccx(), did);
+            let val = get_val(bcx, did, const_ty);
+            DatumBlock(bcx, Datum(val, const_ty, LvalueExpr))
+        }
+        _ => {
+            DatumBlock(bcx, trans_local_var(bcx, def).to_expr_datum())
+        }
+    }
+}
+
+fn trans_rvalue_stmt_unadjusted<'a>(bcx: &'a Block<'a>,
+                                    expr: &ast::Expr)
+                                    -> &'a Block<'a> {
     let mut bcx = bcx;
     let _icx = push_ctxt("trans_rvalue_stmt");
 
@@ -667,38 +743,58 @@ fn trans_rvalue_stmt_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
     }
 
     match expr.node {
+        ast::ExprParen(e) => {
+            trans_into(bcx, e, Ignore)
+        }
         ast::ExprBreak(label_opt) => {
-            return controlflow::trans_break(bcx, label_opt);
+            controlflow::trans_break(bcx, expr.id, label_opt)
         }
         ast::ExprAgain(label_opt) => {
-            return controlflow::trans_cont(bcx, label_opt);
+            controlflow::trans_cont(bcx, expr.id, label_opt)
         }
         ast::ExprRet(ex) => {
-            return controlflow::trans_ret(bcx, ex);
+            controlflow::trans_ret(bcx, ex)
         }
         ast::ExprWhile(cond, body) => {
-            return controlflow::trans_while(bcx, cond, body);
+            controlflow::trans_while(bcx, expr.id, cond, body)
         }
-        ast::ExprLoop(body, opt_label) => {
-            // FIXME #6993: map can go away when ast.rs is changed
-            return controlflow::trans_loop(bcx, body, opt_label.map(|x| x.name));
+        ast::ExprLoop(body, _) => {
+            controlflow::trans_loop(bcx, expr.id, body)
         }
         ast::ExprAssign(dst, src) => {
-            let src_datum = unpack_datum!(
-                bcx, trans_to_datum(bcx, src));
-            let dst_datum = unpack_datum!(
-                bcx, trans_lvalue(bcx, dst));
-            return src_datum.store_to_datum(
-                bcx, DROP_EXISTING, dst_datum);
+            let src_datum = unpack_datum!(bcx, trans(bcx, src));
+            let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign"));
+
+            if ty::type_needs_drop(bcx.tcx(), dst_datum.ty) {
+                // If there are destructors involved, make sure we
+                // are copying from an rvalue, since that cannot possible
+                // alias an lvalue. We are concerned about code like:
+                //
+                //   a = a
+                //
+                // but also
+                //
+                //   a = a.b
+                //
+                // where e.g. a : Option<Foo> and a.b :
+                // Option<Foo>. In that case, freeing `a` before the
+                // assignment may also free `a.b`!
+                //
+                // We could avoid this intermediary with some analysis
+                // to determine whether `dst` may possibly own `src`.
+                let src_datum = unpack_datum!(
+                    bcx, src_datum.to_rvalue_datum(bcx, "ExprAssign"));
+                bcx = glue::drop_ty(bcx, dst_datum.val, dst_datum.ty);
+                src_datum.store_to(bcx, dst_datum.val)
+            } else {
+                src_datum.store_to(bcx, dst_datum.val)
+            }
         }
         ast::ExprAssignOp(callee_id, op, dst, src) => {
-            return trans_assign_op(bcx, expr, callee_id, op, dst, src);
-        }
-        ast::ExprParen(a) => {
-            return trans_rvalue_stmt_unadjusted(bcx, a);
+            trans_assign_op(bcx, expr, callee_id, op, dst, src)
         }
         ast::ExprInlineAsm(ref a) => {
-            return asm::trans_inline_asm(bcx, a);
+            asm::trans_inline_asm(bcx, a)
         }
         _ => {
             bcx.tcx().sess.span_bug(
@@ -707,38 +803,34 @@ fn trans_rvalue_stmt_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
                       fall-through case: {:?}",
                      expr.node));
         }
-    };
+    }
 }
 
-fn trans_rvalue_dps_unadjusted<'a>(
-                               bcx: &'a Block<'a>,
-                               expr: &ast::Expr,
-                               dest: Dest)
-                               -> &'a Block<'a> {
+fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
+                                   expr: &ast::Expr,
+                                   dest: Dest)
+                                   -> &'a Block<'a> {
     let _icx = push_ctxt("trans_rvalue_dps_unadjusted");
+    let mut bcx = bcx;
     let tcx = bcx.tcx();
+    let fcx = bcx.fcx;
 
     match expr.node {
         ast::ExprParen(e) => {
-            return trans_rvalue_dps_unadjusted(bcx, e, dest);
+            return trans_into(bcx, e, dest);
         }
         ast::ExprPath(_) | ast::ExprSelf => {
             return trans_def_dps_unadjusted(bcx, expr,
                                             bcx.def(expr.id), dest);
         }
         ast::ExprIf(cond, thn, els) => {
-            return controlflow::trans_if(bcx, cond, thn, els, dest);
+            return controlflow::trans_if(bcx, expr.id, cond, thn, els, dest);
         }
         ast::ExprMatch(discr, ref arms) => {
             return _match::trans_match(bcx, expr, discr, *arms, dest);
         }
         ast::ExprBlock(blk) => {
-            return base::with_scope(bcx,
-                                    blk.info(),
-                                    "block-expr body",
-                                    |bcx| {
-                controlflow::trans_block(bcx, blk, dest)
-            });
+            controlflow::trans_block(bcx, blk, dest)
         }
         ast::ExprStruct(_, ref fields, base) => {
             return trans_rec_or_struct(bcx, (*fields), base, expr.span, expr.id, dest);
@@ -765,7 +857,9 @@ fn trans_rvalue_dps_unadjusted<'a>(
         }
         ast::ExprVstore(contents, ast::ExprVstoreSlice) |
         ast::ExprVstore(contents, ast::ExprVstoreMutSlice) => {
-            return tvec::trans_slice_vstore(bcx, expr, contents, dest);
+            fcx.push_ast_cleanup_scope(contents.id);
+            bcx = tvec::trans_slice_vstore(bcx, expr, contents, dest);
+            return fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id);
         }
         ast::ExprVec(..) | ast::ExprRepeat(..) => {
             return tvec::trans_fixed_vstore(bcx, expr, expr, dest);
@@ -826,10 +920,11 @@ fn trans_rvalue_dps_unadjusted<'a>(
                                        dest);
         }
         ast::ExprCast(val, _) => {
+            // DPS output mode means this is a trait cast:
             match ty::get(node_id_type(bcx, expr.id)).sty {
                 ty::ty_trait(..) => {
-                    return meth::trans_trait_cast(bcx, val, expr.id,
-                                                  dest, None);
+                    let datum = unpack_datum!(bcx, trans(bcx, val));
+                    return meth::trans_trait_cast(bcx, datum, expr.id, dest);
                 }
                 _ => {
                     bcx.tcx().sess.span_bug(expr.span,
@@ -908,11 +1003,10 @@ fn trans_def_dps_unadjusted<'a>(
     }
 }
 
-fn trans_def_datum_unadjusted<'a>(
-                              bcx: &'a Block<'a>,
-                              ref_expr: &ast::Expr,
-                              def: ast::Def)
-                              -> DatumBlock<'a> {
+fn trans_def_fn_unadjusted<'a>(bcx: &'a Block<'a>,
+                               ref_expr: &ast::Expr,
+                               def: ast::Def) -> DatumBlock<'a, Expr>
+{
     let _icx = push_ctxt("trans_def_datum_unadjusted");
 
     let fn_data = match def {
@@ -928,224 +1022,24 @@ fn trans_def_datum_unadjusted<'a>(
         }
         _ => {
             bcx.tcx().sess.span_bug(ref_expr.span, format!(
-                "Non-DPS def {:?} referened by {}",
-                def, bcx.node_id_to_str(ref_expr.id)));
+                    "trans_def_fn_unadjusted invoked on: {:?} for {}",
+                    def,
+                    ref_expr.repr(bcx.tcx())));
         }
     };
 
     let fn_ty = expr_ty(bcx, ref_expr);
-    DatumBlock {
-        bcx: bcx,
-        datum: Datum {
-            val: fn_data.llfn,
-            ty: fn_ty,
-            mode: ByValue
-        }
-    }
+    DatumBlock(bcx, Datum(fn_data.llfn, fn_ty, RvalueExpr(Rvalue(ByValue))))
 }
 
-fn trans_lvalue_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
-                           -> DatumBlock<'a> {
+pub fn trans_local_var<'a>(bcx: &'a Block<'a>,
+                           def: ast::Def)
+                           -> Datum<Lvalue> {
     /*!
-     *
-     * Translates an lvalue expression, always yielding a by-ref
-     * datum.  Does not apply any adjustments. */
-
-    let _icx = push_ctxt("trans_lval");
-    let mut bcx = bcx;
-
-    debug!("trans_lvalue(expr={})", bcx.expr_to_str(expr));
-    let _indenter = indenter();
-
-    return match expr.node {
-        ast::ExprParen(e) => {
-            trans_lvalue_unadjusted(bcx, e)
-        }
-        ast::ExprPath(_) | ast::ExprSelf => {
-            trans_def_lvalue(bcx, expr, bcx.def(expr.id))
-        }
-        ast::ExprField(base, ident, _) => {
-            trans_rec_field(bcx, base, ident)
-        }
-        ast::ExprIndex(_, base, idx) => {
-            trans_index(bcx, expr, base, idx)
-        }
-        ast::ExprUnary(_, ast::UnDeref, base) => {
-            let basedatum = unpack_datum!(bcx, trans_to_datum(bcx, base));
-            basedatum.deref(bcx, expr, 0)
-        }
-        _ => {
-            bcx.tcx().sess.span_bug(
-                expr.span,
-                format!("trans_lvalue reached fall-through case: {:?}",
-                     expr.node));
-        }
-    };
-
-    fn trans_rec_field<'a>(
-                       bcx: &'a Block<'a>,
-                       base: &ast::Expr,
-                       field: ast::Ident)
-                       -> DatumBlock<'a> {
-        //! Translates `base.field`.
-
-        let mut bcx = bcx;
-        let _icx = push_ctxt("trans_rec_field");
-
-        let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base));
-        let repr = adt::represent_type(bcx.ccx(), base_datum.ty);
-        with_field_tys(bcx.tcx(), base_datum.ty, None, |discr, field_tys| {
-            let ix = ty::field_idx_strict(bcx.tcx(), field.name, field_tys);
-            DatumBlock {
-                datum: base_datum.get_element(bcx,
-                                              field_tys[ix].mt.ty,
-                                              ZeroMem,
-                                              |srcval| {
-                    adt::trans_field_ptr(bcx, repr, srcval, discr, ix)
-                }),
-                bcx: bcx
-            }
-        })
-    }
-
-    fn trans_index<'a>(
-                   bcx: &'a Block<'a>,
-                   index_expr: &ast::Expr,
-                   base: &ast::Expr,
-                   idx: &ast::Expr)
-                   -> DatumBlock<'a> {
-        //! Translates `base[idx]`.
-
-        let _icx = push_ctxt("trans_index");
-        let ccx = bcx.ccx();
-        let mut bcx = bcx;
-
-        let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base));
-
-        // Translate index expression and cast to a suitable LLVM integer.
-        // Rust is less strict than LLVM in this regard.
-        let Result {bcx, val: ix_val} = trans_to_datum(bcx, idx).to_result();
-        let ix_size = machine::llbitsize_of_real(bcx.ccx(), val_ty(ix_val));
-        let int_size = machine::llbitsize_of_real(bcx.ccx(), ccx.int_type);
-        let ix_val = {
-            if ix_size < int_size {
-                if ty::type_is_signed(expr_ty(bcx, idx)) {
-                    SExt(bcx, ix_val, ccx.int_type)
-                } else { ZExt(bcx, ix_val, ccx.int_type) }
-            } else if ix_size > int_size {
-                Trunc(bcx, ix_val, ccx.int_type)
-            } else {
-                ix_val
-            }
-        };
-
-        let vt = tvec::vec_types(bcx, base_datum.ty);
-        base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz");
-
-        let (bcx, base, len) =
-            base_datum.get_vec_base_and_len(bcx, index_expr.span, index_expr.id, 0);
-
-        debug!("trans_index: base {}", bcx.val_to_str(base));
-        debug!("trans_index: len {}", bcx.val_to_str(len));
-
-        let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len);
-        let expect = ccx.intrinsics.get_copy(&("llvm.expect.i1"));
-        let expected = Call(bcx, expect, [bounds_check, C_i1(false)], []);
-        let bcx = with_cond(bcx, expected, |bcx| {
-            controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, len)
-        });
-        let elt = InBoundsGEP(bcx, base, [ix_val]);
-        let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to());
-        return DatumBlock {
-            bcx: bcx,
-            datum: Datum {val: elt,
-                          ty: vt.unit_ty,
-                          mode: ByRef(ZeroMem)}
-        };
-    }
-
-    fn trans_def_lvalue<'a>(
-                        bcx: &'a Block<'a>,
-                        ref_expr: &ast::Expr,
-                        def: ast::Def)
-                        -> DatumBlock<'a> {
-        //! Translates a reference to a path.
-
-        let _icx = push_ctxt("trans_def_lvalue");
-        match def {
-            ast::DefStatic(did, _) => {
-                let const_ty = expr_ty(bcx, ref_expr);
-
-                fn get_did(ccx: @CrateContext, did: ast::DefId)
-                    -> ast::DefId {
-                    if did.crate != ast::LOCAL_CRATE {
-                        inline::maybe_instantiate_inline(ccx, did)
-                    } else {
-                        did
-                    }
-                }
-
-                fn get_val(bcx: &Block, did: ast::DefId, const_ty: ty::t)
-                           -> ValueRef {
-                    // For external constants, we don't inline.
-                    if did.crate == ast::LOCAL_CRATE {
-                        // The LLVM global has the type of its initializer,
-                        // which may not be equal to the enum's type for
-                        // non-C-like enums.
-                        let val = base::get_item_val(bcx.ccx(), did.node);
-                        let pty = type_of::type_of(bcx.ccx(), const_ty).ptr_to();
-                        PointerCast(bcx, val, pty)
-                    } else {
-                        {
-                            let extern_const_values = bcx.ccx()
-                                                         .extern_const_values
-                                                         .borrow();
-                            match extern_const_values.get().find(&did) {
-                                None => {}  // Continue.
-                                Some(llval) => {
-                                    return *llval;
-                                }
-                            }
-                        }
-
-                        unsafe {
-                            let llty = type_of::type_of(bcx.ccx(), const_ty);
-                            let symbol = csearch::get_symbol(
-                                bcx.ccx().sess.cstore,
-                                did);
-                            let llval = symbol.with_c_str(|buf| {
-                                llvm::LLVMAddGlobal(bcx.ccx().llmod,
-                                                    llty.to_ref(),
-                                                    buf)
-                            });
-                            let mut extern_const_values =
-                                bcx.ccx().extern_const_values.borrow_mut();
-                            extern_const_values.get().insert(did, llval);
-                            llval
-                        }
-                    }
-                }
-
-                let did = get_did(bcx.ccx(), did);
-                let val = get_val(bcx, did, const_ty);
-                DatumBlock {
-                    bcx: bcx,
-                    datum: Datum {val: val,
-                                  ty: const_ty,
-                                  mode: ByRef(ZeroMem)}
-                }
-            }
-            _ => {
-                DatumBlock {
-                    bcx: bcx,
-                    datum: trans_local_var(bcx, def)
-                }
-            }
-        }
-    }
-}
+     * Translates a reference to a local variable or argument.
+     * This always results in an lvalue datum.
+     */
 
-pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
     let _icx = push_ctxt("trans_local_var");
 
     return match def {
@@ -1154,13 +1048,7 @@ pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
             let local_ty = node_id_type(bcx, nid);
             let llupvars = bcx.fcx.llupvars.borrow();
             match llupvars.get().find(&nid) {
-                Some(&val) => {
-                    Datum {
-                        val: val,
-                        ty: local_ty,
-                        mode: ByRef(ZeroMem)
-                    }
-                }
+                Some(&val) => Datum(val, local_ty, Lvalue),
                 None => {
                     bcx.sess().bug(format!(
                         "trans_local_var: no llval for upvar {:?} found", nid));
@@ -1196,9 +1084,10 @@ pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
         }
     };
 
-    fn take_local(bcx: &Block,
-                  table: &HashMap<ast::NodeId, Datum>,
-                  nid: ast::NodeId) -> Datum {
+    fn take_local<'a>(bcx: &'a Block<'a>,
+                      table: &HashMap<ast::NodeId, Datum<Lvalue>>,
+                      nid: ast::NodeId)
+                      -> Datum<Lvalue> {
         let datum = match table.find(&nid) {
             Some(&v) => v,
             None => {
@@ -1212,15 +1101,18 @@ fn take_local(bcx: &Block,
     }
 }
 
-// The optional node ID here is the node ID of the path identifying the enum
-// variant in use. If none, this cannot possibly an enum variant (so, if it
-// is and `node_id_opt` is none, this function fails).
-pub fn with_field_tys<R>(
-                      tcx: ty::ctxt,
-                      ty: ty::t,
-                      node_id_opt: Option<ast::NodeId>,
-                      op: |ty::Disr, (&[ty::field])| -> R)
-                      -> R {
+pub fn with_field_tys<R>(tcx: ty::ctxt,
+                         ty: ty::t,
+                         node_id_opt: Option<ast::NodeId>,
+                         op: |ty::Disr, (&[ty::field])| -> R)
+                         -> R {
+    /*!
+     * Helper for enumerating the field types of structs, enums, or records.
+     * The optional node ID here is the node ID of the path identifying the enum
+     * variant in use. If none, this cannot possibly an enum variant (so, if it
+     * is and `node_id_opt` is none, this function fails).
+     */
+
     match ty::get(ty).sty {
         ty::ty_struct(did, ref substs) => {
             op(0, struct_fields(tcx, did, substs))
@@ -1353,6 +1245,7 @@ fn trans_adt<'a>(
              dest: Dest)
              -> &'a Block<'a> {
     let _icx = push_ctxt("trans_adt");
+    let fcx = bcx.fcx;
     let mut bcx = bcx;
     let addr = match dest {
         Ignore => {
@@ -1367,44 +1260,49 @@ fn trans_adt<'a>(
         }
         SaveIn(pos) => pos
     };
-    let mut temp_cleanups = ~[];
+
+    // This scope holds intermediates that must be cleaned should
+    // failure occur before the ADT as a whole is ready.
+    let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
+
     adt::trans_start_init(bcx, repr, addr, discr);
+
     for &(i, e) in fields.iter() {
         let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
         let e_ty = expr_ty_adjusted(bcx, e);
         bcx = trans_into(bcx, e, SaveIn(dest));
-        add_clean_temp_mem(bcx, dest, e_ty);
-        temp_cleanups.push(dest);
+        fcx.schedule_drop_mem(cleanup::CustomScope(custom_cleanup_scope),
+                              dest, e_ty);
     }
+
     for base in optbase.iter() {
         // FIXME #6573: is it sound to use the destination's repr on the base?
         // And, would it ever be reasonable to be here with discr != 0?
-        let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base.expr));
+        let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base.expr, "base"));
         for &(i, t) in base.fields.iter() {
-            let datum = base_datum.get_element(bcx, t, ZeroMem, |srcval| {
-                adt::trans_field_ptr(bcx, repr, srcval, discr, i)
-            });
+            let datum = base_datum.get_element(
+                t,
+                |srcval| adt::trans_field_ptr(bcx, repr, srcval, discr, i));
             let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
-            bcx = datum.store_to(bcx, INIT, dest);
+            bcx = datum.store_to(bcx, dest);
         }
     }
 
-    for cleanup in temp_cleanups.iter() {
-        revoke_clean(bcx, *cleanup);
-    }
+    fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
+
     return bcx;
 }
 
 
-fn trans_immediate_lit<'a>(
-                       bcx: &'a Block<'a>,
-                       expr: &ast::Expr,
-                       lit: ast::Lit)
-                       -> DatumBlock<'a> {
+fn trans_immediate_lit<'a>(bcx: &'a Block<'a>,
+                           expr: &ast::Expr,
+                           lit: ast::Lit)
+                           -> DatumBlock<'a, Expr> {
     // must not be a string constant, that is a RvalueDpsExpr
     let _icx = push_ctxt("trans_immediate_lit");
     let ty = expr_ty(bcx, expr);
-    immediate_rvalue_bcx(bcx, consts::const_lit(bcx.ccx(), expr, lit), ty)
+    let v = consts::const_lit(bcx.ccx(), expr, lit);
+    immediate_rvalue_bcx(bcx, v, ty).to_expr_datumblock()
 }
 
 fn trans_unary_datum<'a>(
@@ -1412,7 +1310,8 @@ fn trans_unary_datum<'a>(
                      un_expr: &ast::Expr,
                      op: ast::UnOp,
                      sub_expr: &ast::Expr)
-                     -> DatumBlock<'a> {
+                     -> DatumBlock<'a, Expr> {
+    let mut bcx = bcx;
     let _icx = push_ctxt("trans_unary_datum");
 
     // if deref, would be LvalueExpr
@@ -1429,25 +1328,23 @@ fn trans_unary_datum<'a>(
 
     return match op {
         ast::UnNot => {
-            let Result {bcx, val} = trans_to_datum(bcx, sub_expr).to_result();
-
-            // If this is a boolean type, we must not use the LLVM Not
-            // instruction, as that is a *bitwise* not and we want *logical*
-            // not on our 8-bit boolean values.
-            let llresult = match ty::get(un_ty).sty {
-                ty::ty_bool => {
-                    let llcond = ICmp(bcx,
-                                      lib::llvm::IntEQ,
-                                      val,
-                                      C_bool(false));
-                    Select(bcx, llcond, C_bool(true), C_bool(false))
-                }
-                _ => Not(bcx, val)
+            let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
+            let llresult = if ty::type_is_bool(un_ty) {
+                let val = datum.to_llscalarish(bcx);
+                let llcond = ICmp(bcx,
+                                  lib::llvm::IntEQ,
+                                  val,
+                                  C_bool(false));
+                Select(bcx, llcond, C_bool(true), C_bool(false))
+            } else {
+                // Note: `Not` is bitwise, not suitable for logical not.
+                Not(bcx, datum.to_llscalarish(bcx))
             };
-            immediate_rvalue_bcx(bcx, llresult, un_ty)
+            immediate_rvalue_bcx(bcx, llresult, un_ty).to_expr_datumblock()
         }
         ast::UnNeg => {
-            let Result {bcx, val} = trans_to_datum(bcx, sub_expr).to_result();
+            let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
+            let val = datum.to_llscalarish(bcx);
             let llneg = {
                 if ty::type_is_fp(un_ty) {
                     FNeg(bcx, val)
@@ -1455,14 +1352,13 @@ fn trans_unary_datum<'a>(
                     Neg(bcx, val)
                 }
             };
-            immediate_rvalue_bcx(bcx, llneg, un_ty)
+            immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock()
         }
         ast::UnBox => {
             trans_boxed_expr(bcx, un_ty, sub_expr, sub_ty, heap_managed)
         }
         ast::UnUniq => {
-            let heap  = heap_for_unique(bcx, un_ty);
-            trans_boxed_expr(bcx, un_ty, sub_expr, sub_ty, heap)
+            trans_boxed_expr(bcx, un_ty, sub_expr, sub_ty, heap_exchange)
         }
         ast::UnDeref => {
             bcx.sess().bug("deref expressions should have been \
@@ -1472,50 +1368,49 @@ fn trans_unary_datum<'a>(
     };
 }
 
-fn trans_boxed_expr<'a>(
-                    bcx: &'a Block<'a>,
-                    box_ty: ty::t,
-                    contents: &ast::Expr,
-                    contents_ty: ty::t,
-                    heap: heap)
-                    -> DatumBlock<'a> {
+fn trans_boxed_expr<'a>(bcx: &'a Block<'a>,
+                        box_ty: ty::t,
+                        contents: &ast::Expr,
+                        contents_ty: ty::t,
+                        heap: heap)
+                        -> DatumBlock<'a, Expr> {
     let _icx = push_ctxt("trans_boxed_expr");
+    let fcx = bcx.fcx;
     if heap == heap_exchange {
         let llty = type_of::type_of(bcx.ccx(), contents_ty);
         let size = llsize_of(bcx.ccx(), llty);
         let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
                                                            heap_exchange, size);
-        add_clean_free(bcx, val, heap_exchange);
+        let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
+        fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
+                                val, heap_exchange);
         let bcx = trans_into(bcx, contents, SaveIn(val));
-        revoke_clean(bcx, val);
-        return immediate_rvalue_bcx(bcx, val, box_ty);
+        fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
+        immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
     } else {
-        let base::MallocResult {
-            bcx,
-            smart_ptr: bx,
-            body
-        } = base::malloc_general(bcx, contents_ty, heap);
-        add_clean_free(bcx, bx, heap);
+        let base::MallocResult { bcx, smart_ptr: bx, body } =
+            base::malloc_general(bcx, contents_ty, heap);
+        let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
+        fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
+                                bx, heap);
         let bcx = trans_into(bcx, contents, SaveIn(body));
-        revoke_clean(bcx, bx);
-        return immediate_rvalue_bcx(bcx, bx, box_ty);
+        fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
+        immediate_rvalue_bcx(bcx, bx, box_ty).to_expr_datumblock()
     }
 }
 
-fn trans_addr_of<'a>(
-                 bcx: &'a Block<'a>,
-                 expr: &ast::Expr,
-                 subexpr: &ast::Expr)
-                 -> DatumBlock<'a> {
+fn trans_addr_of<'a>(bcx: &'a Block<'a>,
+                     expr: &ast::Expr,
+                     subexpr: &ast::Expr)
+                     -> DatumBlock<'a, Expr> {
     let _icx = push_ctxt("trans_addr_of");
     let mut bcx = bcx;
-    let sub_datum = unpack_datum!(bcx, trans_to_datum(bcx, subexpr));
-    let llval = sub_datum.to_ref_llval(bcx);
-    return immediate_rvalue_bcx(bcx, llval, expr_ty(bcx, expr));
+    let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of"));
+    let ty = expr_ty(bcx, expr);
+    return immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock();
 }
 
-pub fn trans_gc<'a>(
-                mut bcx: &'a Block<'a>,
+fn trans_gc<'a>(mut bcx: &'a Block<'a>,
                 expr: &ast::Expr,
                 contents: &ast::Expr,
                 dest: Dest)
@@ -1538,13 +1433,12 @@ pub fn trans_gc<'a>(
     let repr = adt::represent_type(bcx.ccx(), expr_ty);
     adt::trans_start_init(bcx, repr, addr, 0);
     let field_dest = adt::trans_field_ptr(bcx, repr, addr, 0, 0);
-    let contents_datum_block = trans_boxed_expr(bcx,
-                                                box_ty,
-                                                contents,
-                                                contents_ty,
-                                                heap_managed);
-    bcx = contents_datum_block.bcx;
-    bcx = contents_datum_block.datum.move_to(bcx, INIT, field_dest);
+    let contents_datum = unpack_datum!(bcx, trans_boxed_expr(bcx,
+                                                             box_ty,
+                                                             contents,
+                                                             contents_ty,
+                                                             heap_managed));
+    bcx = contents_datum.store_to(bcx, field_dest);
 
     // Next, wrap it up in the struct.
     bcx
@@ -1557,17 +1451,13 @@ fn trans_eager_binop<'a>(
                      binop_expr: &ast::Expr,
                      binop_ty: ty::t,
                      op: ast::BinOp,
-                     lhs_datum: &Datum,
-                     rhs_datum: &Datum)
-                     -> DatumBlock<'a> {
+                     lhs_t: ty::t,
+                     lhs: ValueRef,
+                     rhs_t: ty::t,
+                     rhs: ValueRef)
+                     -> DatumBlock<'a, Expr> {
     let _icx = push_ctxt("trans_eager_binop");
 
-    let lhs = lhs_datum.to_appropriate_llval(bcx);
-    let lhs_t = lhs_datum.ty;
-
-    let rhs = rhs_datum.to_appropriate_llval(bcx);
-    let rhs_t = rhs_datum.ty;
-
     let mut intype = {
         if ty::type_is_bot(lhs_t) { rhs_t }
         else { lhs_t }
@@ -1650,7 +1540,7 @@ fn trans_eager_binop<'a>(
       }
     };
 
-    return immediate_rvalue_bcx(bcx, val, binop_ty);
+    immediate_rvalue_bcx(bcx, val, binop_ty).to_expr_datumblock()
 }
 
 // refinement types would obviate the need for this
@@ -1665,23 +1555,20 @@ fn trans_lazy_binop<'a>(
                     op: lazy_binop_ty,
                     a: &ast::Expr,
                     b: &ast::Expr)
-                    -> DatumBlock<'a> {
+                    -> DatumBlock<'a, Expr> {
     let _icx = push_ctxt("trans_lazy_binop");
     let binop_ty = expr_ty(bcx, binop_expr);
-    let bcx = bcx;
+    let fcx = bcx.fcx;
 
-    let Result {bcx: past_lhs, val: lhs} = {
-        base::with_scope_result(bcx, a.info(), "lhs", |bcx| {
-            trans_to_datum(bcx, a).to_result()
-        })
-    };
+    let DatumBlock {bcx: past_lhs, datum: lhs} = trans(bcx, a);
+    let lhs = lhs.to_llscalarish(past_lhs);
 
     if past_lhs.unreachable.get() {
-        return immediate_rvalue_bcx(past_lhs, lhs, binop_ty);
+        return immediate_rvalue_bcx(past_lhs, lhs, binop_ty).to_expr_datumblock();
     }
 
-    let join = base::sub_block(bcx, "join");
-    let before_rhs = base::sub_block(bcx, "rhs");
+    let join = fcx.new_id_block("join", binop_expr.id);
+    let before_rhs = fcx.new_id_block("before_rhs", b.id);
 
     let lhs_i1 = bool_to_i1(past_lhs, lhs);
     match op {
@@ -1689,21 +1576,18 @@ fn trans_lazy_binop<'a>(
       lazy_or => CondBr(past_lhs, lhs_i1, join.llbb, before_rhs.llbb)
     }
 
-    let Result {bcx: past_rhs, val: rhs} = {
-        base::with_scope_result(before_rhs, b.info(), "rhs", |bcx| {
-            trans_to_datum(bcx, b).to_result()
-        })
-    };
+    let DatumBlock {bcx: past_rhs, datum: rhs} = trans(before_rhs, b);
+    let rhs = rhs.to_llscalarish(past_rhs);
 
     if past_rhs.unreachable.get() {
-        return immediate_rvalue_bcx(join, lhs, binop_ty);
+        return immediate_rvalue_bcx(join, lhs, binop_ty).to_expr_datumblock();
     }
 
     Br(past_rhs, join.llbb);
     let phi = Phi(join, Type::bool(), [lhs, rhs], [past_lhs.llbb,
-                                               past_rhs.llbb]);
+                                                   past_rhs.llbb]);
 
-    return immediate_rvalue_bcx(join, phi, binop_ty);
+    return immediate_rvalue_bcx(join, phi, binop_ty).to_expr_datumblock();
 }
 
 fn trans_binary<'a>(
@@ -1712,8 +1596,9 @@ fn trans_binary<'a>(
                 op: ast::BinOp,
                 lhs: &ast::Expr,
                 rhs: &ast::Expr)
-                -> DatumBlock<'a> {
+                -> DatumBlock<'a, Expr> {
     let _icx = push_ctxt("trans_binary");
+    let ccx = bcx.ccx();
 
     match op {
         ast::BiAnd => {
@@ -1724,11 +1609,23 @@ fn trans_binary<'a>(
         }
         _ => {
             let mut bcx = bcx;
-            let lhs_datum = unpack_datum!(bcx, trans_to_datum(bcx, lhs));
-            let rhs_datum = unpack_datum!(bcx, trans_to_datum(bcx, rhs));
+            let lhs_datum = unpack_datum!(bcx, trans(bcx, lhs));
+            let rhs_datum = unpack_datum!(bcx, trans(bcx, rhs));
             let binop_ty = expr_ty(bcx, binop_expr);
+
+            debug!("trans_binary (expr {}): lhs_datum={}",
+                   binop_expr.id,
+                   lhs_datum.to_str(ccx));
+            let lhs_ty = lhs_datum.ty;
+            let lhs = lhs_datum.to_llscalarish(bcx);
+
+            debug!("trans_binary (expr {}): rhs_datum={}",
+                   binop_expr.id,
+                   rhs_datum.to_str(ccx));
+            let rhs_ty = rhs_datum.ty;
+            let rhs = rhs_datum.to_llscalarish(bcx);
             trans_eager_binop(bcx, binop_expr, binop_ty, op,
-                              &lhs_datum, &rhs_datum)
+                              lhs_ty, lhs, rhs_ty, rhs)
         }
     }
 }
@@ -1748,14 +1645,15 @@ fn trans_overloaded_op<'a>(
     };
     let fty = node_id_type(bcx, callee_id);
     callee::trans_call_inner(bcx,
-                             expr.info(),
+                             Some(expr_info(expr)),
                              fty,
                              ret_ty,
-                             |bcx| {
+                             |bcx, arg_cleanup_scope| {
                                 meth::trans_method_callee(bcx,
                                                           callee_id,
                                                           rcvr,
-                                                          origin)
+                                                          origin,
+                                                          arg_cleanup_scope)
                              },
                              callee::ArgExprs(args),
                              Some(dest),
@@ -1823,85 +1721,90 @@ pub fn cast_type_kind(t: ty::t) -> cast_kind {
     }
 }
 
-fn trans_imm_cast<'a>(bcx: &'a Block<'a>, expr: &ast::Expr, id: ast::NodeId)
-                  -> DatumBlock<'a> {
+fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
+                      expr: &ast::Expr,
+                      id: ast::NodeId)
+                      -> DatumBlock<'a, Expr> {
     let _icx = push_ctxt("trans_cast");
+    let mut bcx = bcx;
     let ccx = bcx.ccx();
 
-    let t_out = node_id_type(bcx, id);
-
-    let mut bcx = bcx;
-    let llexpr = unpack_result!(bcx, trans_to_datum(bcx, expr).to_result());
-    let ll_t_in = val_ty(llexpr);
     let t_in = expr_ty(bcx, expr);
-    let ll_t_out = type_of::type_of(ccx, t_out);
-
+    let t_out = node_id_type(bcx, id);
     let k_in = cast_type_kind(t_in);
     let k_out = cast_type_kind(t_out);
     let s_in = k_in == cast_integral && ty::type_is_signed(t_in);
+    let ll_t_in = type_of::type_of(ccx, t_in);
+    let ll_t_out = type_of::type_of(ccx, t_out);
 
-    let newval =
-        match (k_in, k_out) {
-            (cast_integral, cast_integral) => {
-                int_cast(bcx, ll_t_out, ll_t_in, llexpr, s_in)
-            }
-            (cast_float, cast_float) => {
-                float_cast(bcx, ll_t_out, ll_t_in, llexpr)
-            }
-            (cast_integral, cast_float) => {
-                if s_in {
-                    SIToFP(bcx, llexpr, ll_t_out)
-                } else { UIToFP(bcx, llexpr, ll_t_out) }
-            }
-            (cast_float, cast_integral) => {
-                if ty::type_is_signed(t_out) {
-                    FPToSI(bcx, llexpr, ll_t_out)
-                } else { FPToUI(bcx, llexpr, ll_t_out) }
-            }
-            (cast_integral, cast_pointer) => {
-                IntToPtr(bcx, llexpr, ll_t_out)
-            }
-            (cast_pointer, cast_integral) => {
-                PtrToInt(bcx, llexpr, ll_t_out)
-            }
-            (cast_pointer, cast_pointer) => {
-                PointerCast(bcx, llexpr, ll_t_out)
-            }
-            (cast_enum, cast_integral) |
-            (cast_enum, cast_float) => {
-                let bcx = bcx;
-                let repr = adt::represent_type(ccx, t_in);
-                let llexpr_ptr;
-                if type_is_immediate(ccx, t_in) {
-                    llexpr_ptr = Alloca(bcx, ll_t_in, "");
-                    Store(bcx, llexpr, llexpr_ptr);
-                } else {
-                    llexpr_ptr = llexpr;
-                }
-                let lldiscrim_a = adt::trans_get_discr(bcx, repr, llexpr_ptr, Some(Type::i64()));
-                match k_out {
-                    cast_integral => int_cast(bcx, ll_t_out,
-                                              val_ty(lldiscrim_a),
-                                              lldiscrim_a, true),
-                    cast_float => SIToFP(bcx, lldiscrim_a, ll_t_out),
-                    _ => ccx.sess.bug(format!("translating unsupported cast: \
-                                           {} ({:?}) -> {} ({:?})",
-                                           t_in.repr(ccx.tcx), k_in,
-                                           t_out.repr(ccx.tcx), k_out))
-                }
+    // Convert the value to be cast into a ValueRef, either by-ref or
+    // by-value as appropriate given its type:
+    let datum = unpack_datum!(bcx, trans(bcx, expr));
+    let newval = match (k_in, k_out) {
+        (cast_integral, cast_integral) => {
+            let llexpr = datum.to_llscalarish(bcx);
+            int_cast(bcx, ll_t_out, ll_t_in, llexpr, s_in)
+        }
+        (cast_float, cast_float) => {
+            let llexpr = datum.to_llscalarish(bcx);
+            float_cast(bcx, ll_t_out, ll_t_in, llexpr)
+        }
+        (cast_integral, cast_float) => {
+            let llexpr = datum.to_llscalarish(bcx);
+            if s_in {
+                SIToFP(bcx, llexpr, ll_t_out)
+            } else { UIToFP(bcx, llexpr, ll_t_out) }
+        }
+        (cast_float, cast_integral) => {
+            let llexpr = datum.to_llscalarish(bcx);
+            if ty::type_is_signed(t_out) {
+                FPToSI(bcx, llexpr, ll_t_out)
+            } else { FPToUI(bcx, llexpr, ll_t_out) }
+        }
+        (cast_integral, cast_pointer) => {
+            let llexpr = datum.to_llscalarish(bcx);
+            IntToPtr(bcx, llexpr, ll_t_out)
+        }
+        (cast_pointer, cast_integral) => {
+            let llexpr = datum.to_llscalarish(bcx);
+            PtrToInt(bcx, llexpr, ll_t_out)
+        }
+        (cast_pointer, cast_pointer) => {
+            let llexpr = datum.to_llscalarish(bcx);
+            PointerCast(bcx, llexpr, ll_t_out)
+        }
+        (cast_enum, cast_integral) |
+        (cast_enum, cast_float) => {
+            let mut bcx = bcx;
+            let repr = adt::represent_type(ccx, t_in);
+            let datum = unpack_datum!(
+                bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
+            let llexpr_ptr = datum.to_llref();
+            let lldiscrim_a =
+                adt::trans_get_discr(bcx, repr, llexpr_ptr, Some(Type::i64()));
+            match k_out {
+                cast_integral => int_cast(bcx, ll_t_out,
+                                          val_ty(lldiscrim_a),
+                                          lldiscrim_a, true),
+                cast_float => SIToFP(bcx, lldiscrim_a, ll_t_out),
+                _ => ccx.sess.bug(format!("translating unsupported cast: \
+                                          {} ({:?}) -> {} ({:?})",
+                                          t_in.repr(ccx.tcx), k_in,
+                                          t_out.repr(ccx.tcx), k_out))
             }
-            _ => ccx.sess.bug(format!("translating unsupported cast: \
-                                   {} ({:?}) -> {} ({:?})",
-                                   t_in.repr(ccx.tcx), k_in,
-                                   t_out.repr(ccx.tcx), k_out))
-        };
-    return immediate_rvalue_bcx(bcx, newval, t_out);
+        }
+        _ => ccx.sess.bug(format!("translating unsupported cast: \
+                                  {} ({:?}) -> {} ({:?})",
+                                  t_in.repr(ccx.tcx), k_in,
+                                  t_out.repr(ccx.tcx), k_out))
+    };
+    return immediate_rvalue_bcx(bcx, newval, t_out).to_expr_datumblock();
 }
 
 fn trans_assign_op<'a>(
                    bcx: &'a Block<'a>,
                    expr: &ast::Expr,
-                   callee_id: ast::NodeId,
+                   _callee_id: ast::NodeId,
                    op: ast::BinOp,
                    dst: &ast::Expr,
                    src: @ast::Expr)
@@ -1911,40 +1814,32 @@ fn trans_assign_op<'a>(
 
     debug!("trans_assign_op(expr={})", bcx.expr_to_str(expr));
 
-    // Evaluate LHS (destination), which should be an lvalue
-    let dst_datum = unpack_datum!(bcx, trans_lvalue_unadjusted(bcx, dst));
+    // User-defined operator methods cannot be used with `+=` etc right now
+    assert!({
+            let method_map = bcx.ccx().maps.method_map.borrow();
+            !method_map.get().find(&expr.id).is_some()
+        });
 
-    // A user-defined operator method
-    let found = {
-        let method_map = bcx.ccx().maps.method_map.borrow();
-        method_map.get().find(&expr.id).is_some()
-    };
-    if found {
-        // FIXME(#2528) evaluates the receiver twice!!
-        let scratch = scratch_datum(bcx, dst_datum.ty, "__assign_op", false);
-        let bcx = trans_overloaded_op(bcx,
-                                      expr,
-                                      callee_id,
-                                      dst,
-                                      ~[src],
-                                      dst_datum.ty,
-                                      SaveIn(scratch.val));
-        return scratch.move_to_datum(bcx, DROP_EXISTING, dst_datum);
-    }
+    // Evaluate LHS (destination), which should be an lvalue
+    let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
+    assert!(!ty::type_needs_drop(bcx.tcx(), dst_datum.ty));
+    let dst_ty = dst_datum.ty;
+    let dst = Load(bcx, dst_datum.val);
 
-    // Evaluate RHS (source)
-    let src_datum = unpack_datum!(bcx, trans_to_datum(bcx, src));
+    // Evaluate RHS
+    let rhs_datum = unpack_datum!(bcx, trans(bcx, src));
+    let rhs_ty = rhs_datum.ty;
+    let rhs = rhs_datum.to_llscalarish(bcx);
 
     // Perform computation and store the result
-    let result_datum =
-        unpack_datum!(bcx,
-                      trans_eager_binop(
-                          bcx, expr, dst_datum.ty, op,
-                          &dst_datum, &src_datum));
-    return result_datum.copy_to_datum(bcx, DROP_EXISTING, dst_datum);
+    let result_datum = unpack_datum!(
+        bcx, trans_eager_binop(bcx, expr, dst_datum.ty, op,
+                               dst_ty, dst, rhs_ty, rhs));
+    return result_datum.store_to(bcx, dst_datum.val);
 }
 
-pub fn trans_log_level<'a>(bcx: &'a Block<'a>) -> DatumBlock<'a> {
+fn trans_log_level<'a>(bcx: &'a Block<'a>)
+                       -> DatumBlock<'a, Expr> {
     let _icx = push_ctxt("trans_log_level");
     let ccx = bcx.ccx();
 
@@ -1998,6 +1893,193 @@ pub fn trans_log_level<'a>(bcx: &'a Block<'a>) -> DatumBlock<'a> {
         }
     };
 
-    return immediate_rvalue_bcx(bcx, Load(bcx, global), ty::mk_u32());
+    immediate_rvalue_bcx(bcx, Load(bcx, global), ty::mk_u32()).to_expr_datumblock()
+}
+
+fn deref_multiple<'a>(bcx: &'a Block<'a>,
+                      expr: &ast::Expr,
+                      datum: Datum<Expr>,
+                      times: uint)
+                      -> DatumBlock<'a, Expr> {
+    let mut bcx = bcx;
+    let mut datum = datum;
+    for i in range(1, times+1) {
+        datum = unpack_datum!(bcx, deref_once(bcx, expr, datum, i));
+    }
+    DatumBlock { bcx: bcx, datum: datum }
+}
+
+fn deref_once<'a>(bcx: &'a Block<'a>,
+                  expr: &ast::Expr,
+                  datum: Datum<Expr>,
+                  derefs: uint)
+                  -> DatumBlock<'a, Expr> {
+    let ccx = bcx.ccx();
+    let bcx = write_guard::root_and_write_guard(&datum, bcx, expr.span,
+                                                expr.id, derefs);
+
+    debug!("deref_once(expr={}, datum={}, derefs={})",
+           expr.repr(bcx.tcx()),
+           datum.to_str(ccx),
+           derefs);
+
+    let mut bcx = bcx;
+
+    let r = match ty::get(datum.ty).sty {
+        ty::ty_uniq(content_ty) => {
+            deref_owned_pointer(bcx, expr, datum, content_ty)
+        }
+
+        ty::ty_box(content_ty) => {
+            let datum = unpack_datum!(
+                bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
+            let llptrref = datum.to_llref();
+            let llptr = Load(bcx, llptrref);
+            let llbody = GEPi(bcx, llptr, [0u, abi::box_field_body]);
+            DatumBlock(bcx, Datum(llbody, content_ty, LvalueExpr))
+        }
+
+        ty::ty_ptr(ty::mt { ty: content_ty, .. }) |
+        ty::ty_rptr(_, ty::mt { ty: content_ty, .. }) => {
+            assert!(!ty::type_needs_drop(bcx.tcx(), datum.ty));
+
+            let ptr = datum.to_llscalarish(bcx);
+
+            // Always generate an lvalue datum, even if datum.mode is
+            // an rvalue.  This is because datum.mode is only an
+            // rvalue for non-owning pointers like &T or *T, in which
+            // case cleanup *is* scheduled elsewhere, by the true
+            // owner (or, in the case of *T, by the user).
+            DatumBlock(bcx, Datum(ptr, content_ty, LvalueExpr))
+        }
+
+        ty::ty_enum(..) |
+        ty::ty_struct(..) => {
+            // Subtle efficiency note: In the case where we have a
+            // newtype struct where the struct itself does not have a
+            // dtor, but the contents do, we could avoid forcing the
+            // data into Lvalue and instead return an Rvalue. But it
+            // doesn't seem worth the trouble.
+            let datum = unpack_datum!(bcx, ensure_cleanup(bcx, expr, datum));
+
+            // Unlike the pointer case above, we generate an
+            // rvalue datum if we are given an rvalue. There are
+            // two reasons that this makes sense here:
+            //
+            // 1. dereferencing a struct does not actually perform a
+            //    pointer load and hence the resulting value is not
+            //    naturally by reference, as would be required by an
+            //    lvalue result.
+            //
+            // 2. the struct always owns its contents, and hence and does not
+            //    itself have a dtor (else it would be in lvalue mode).
+            let repr = adt::represent_type(ccx, datum.ty);
+            let ty = adt::deref_ty(ccx, repr);
+            let Datum { val, kind, .. } = datum;
+            let r = match kind {
+                LvalueExpr => {
+                    Datum {
+                        val: adt::trans_field_ptr(bcx, repr, val, 0, 0),
+                        ty: ty,
+                        kind: LvalueExpr
+                    }
+                }
+                RvalueExpr(Rvalue { mode: ByRef }) => {
+                    Datum {
+                        val: adt::trans_field_ptr(bcx, repr, val, 0, 0),
+                        ty: ty,
+                        kind: RvalueExpr(Rvalue(ByValue))
+                    }
+                }
+                RvalueExpr(Rvalue { mode: ByValue }) => {
+                    Datum {
+                        val: ExtractValue(bcx, val, 0),
+                        ty: ty,
+                        kind: RvalueExpr(Rvalue(ByValue))
+                    }
+                }
+            };
+            DatumBlock(bcx, r)
+        }
+
+        _ => {
+            bcx.tcx().sess.span_bug(
+                expr.span,
+                format!("deref invoked on expr of illegal type {}",
+                        datum.ty.repr(bcx.tcx())));
+        }
+    };
+
+    debug!("deref_once(expr={}, derefs={}, result={})",
+           expr.id, derefs, r.datum.to_str(ccx));
+
+    return r;
+
+    fn ensure_cleanup<'a>(mut bcx: &'a Block<'a>,
+                          expr: &ast::Expr,
+                          datum: Datum<Expr>)
+                          -> DatumBlock<'a, Expr> {
+        /*!
+         * If the datum contains data that needs to be dropped,
+         * convert it to an lvalue, thus ensuring that cleanup
+         * is scheduled.
+         */
+
+        if ty::type_needs_drop(bcx.tcx(), datum.ty) {
+            let lv_datum = unpack_datum!(
+                bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
+            DatumBlock(bcx, lv_datum.to_expr_datum())
+        } else {
+            DatumBlock(bcx, datum)
+        }
+    }
+
+    fn deref_owned_pointer<'a>(bcx: &'a Block<'a>,
+                               expr: &ast::Expr,
+                               datum: Datum<Expr>,
+                               content_ty: ty::t)
+                               -> DatumBlock<'a, Expr> {
+        /*!
+         * We microoptimize derefs of owned pointers a bit here.
+         * Basically, the idea is to make the deref of an rvalue
+         * result in an rvalue. This helps to avoid intermediate stack
+         * slots in the resulting LLVM. The idea here is that, if the
+         * `~T` pointer is an rvalue, then we can schedule a *shallow*
+         * free of the `~T` pointer, and then return a ByRef rvalue
+         * into the pointer. Because the free is shallow, it is legit
+         * to return an rvalue, because we know that the contents are
+         * not yet scheduled to be freed. The language rules ensure that the
+         * contents will be used (or moved) before the free occurs.
+         */
+
+        match datum.kind {
+            RvalueExpr(Rvalue { mode: ByRef }) => {
+                let scope = cleanup::temporary_scope(bcx.tcx(), expr.id);
+                let ptr = Load(bcx, datum.val);
+                bcx.fcx.schedule_free_value(scope, ptr, heap_exchange);
+            }
+            RvalueExpr(Rvalue { mode: ByValue }) => {
+                let scope = cleanup::temporary_scope(bcx.tcx(), expr.id);
+                bcx.fcx.schedule_free_value(scope, datum.val, heap_exchange);
+            }
+            LvalueExpr => { }
+        }
+
+        // If we had an rvalue in, we produce an rvalue out.
+        let (llptr, kind) = match datum.kind {
+            LvalueExpr => {
+                (Load(bcx, datum.val), LvalueExpr)
+            }
+            RvalueExpr(Rvalue { mode: ByRef }) => {
+                (Load(bcx, datum.val), RvalueExpr(Rvalue(ByRef)))
+            }
+            RvalueExpr(Rvalue { mode: ByValue }) => {
+                (datum.val, RvalueExpr(Rvalue(ByRef)))
+            }
+        };
+
+        let datum = Datum { ty: content_ty, val: llptr, kind: kind };
+        DatumBlock { bcx: bcx, datum: datum }
+    }
 }
 
index 304edb2c31243b1beae71beb0be154ca8930df12..083a1c6988d83a7dead9e3e660293c47efda1739 100644 (file)
@@ -150,11 +150,8 @@ pub fn register_foreign_item_fn(ccx: @CrateContext,
     let llfn;
     {
         let mut externs = ccx.externs.borrow_mut();
-        llfn = base::get_extern_fn(externs.get(),
-                                   ccx.llmod,
-                                   lname,
-                                   cc,
-                                   llfn_ty);
+        llfn = base::get_extern_fn(externs.get(), ccx.llmod, lname,
+                                   cc, llfn_ty, tys.fn_sig.output);
     };
     add_argument_attributes(&tys, llfn);
 
@@ -201,7 +198,7 @@ pub fn trans_native_call<'a>(
         _ => ccx.sess.bug("trans_native_call called on non-function type")
     };
     let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys);
-    let ret_def = !ty::type_is_voidish(bcx.tcx(), fn_sig.output);
+    let ret_def = !return_type_is_void(bcx.ccx(), fn_sig.output);
     let fn_type = cabi::compute_abi_info(ccx,
                                          llsig.llarg_tys,
                                          llsig.llret_ty,
@@ -285,20 +282,20 @@ pub fn trans_native_call<'a>(
             // FIXME(#8357) We really ought to report a span here
             ccx.sess.fatal(
                 format!("ABI string `{}` has no suitable ABI \
-                      for target architecture",
-                     fn_abis.user_string(ccx.tcx)));
+                        for target architecture",
+                        fn_abis.user_string(ccx.tcx)));
         }
     };
 
     // A function pointer is called without the declaration available, so we have to apply
     // any attributes with ABI implications directly to the call instruction. Right now, the
     // only attribute we need to worry about is `sret`.
-    let attrs;
-    if fn_type.ret_ty.is_indirect() {
-        attrs = &[(1, StructRetAttribute)];
+    let sret_attr = if fn_type.ret_ty.is_indirect() {
+        Some((1, StructRetAttribute))
     } else {
-        attrs = &[];
-    }
+        None
+    };
+    let attrs = sret_attr.as_slice();
     let llforeign_retval = CallWithConv(bcx, llfn, llargs_foreign, cc, attrs);
 
     // If the function we just called does not use an outpointer,
@@ -417,19 +414,14 @@ pub fn register_rust_fn_with_foreign_abi(ccx: @CrateContext,
     let tys = foreign_types_for_id(ccx, node_id);
     let llfn_ty = lltype_for_fn_from_foreign_types(&tys);
     let t = ty::node_id_to_type(ccx.tcx, node_id);
-    let cconv = match ty::get(t).sty {
+    let (cconv, output) = match ty::get(t).sty {
         ty::ty_bare_fn(ref fn_ty) => {
             let c = llvm_calling_convention(ccx, fn_ty.abis);
-            c.unwrap_or(lib::llvm::CCallConv)
+            (c.unwrap_or(lib::llvm::CCallConv), fn_ty.sig.output)
         }
-        _ => lib::llvm::CCallConv
+        _ => fail!("expected bare fn in register_rust_fn_with_foreign_abi")
     };
-    let llfn = base::register_fn_llvmty(ccx,
-                                        sp,
-                                        sym,
-                                        node_id,
-                                        cconv,
-                                        llfn_ty);
+    let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty, output);
     add_argument_attributes(&tys, llfn);
     debug!("register_rust_fn_with_foreign_abi(node_id={:?}, llfn_ty={}, llfn={})",
            node_id, ccx.tn.type_to_str(llfn_ty), ccx.tn.val_to_str(llfn));
@@ -499,7 +491,6 @@ fn build_rust_fn(ccx: @CrateContext,
                        None,
                        None,
                        id,
-                       None,
                        []);
         return llfndecl;
     }
@@ -787,7 +778,7 @@ fn foreign_types_for_fn_ty(ccx: &CrateContext,
         _ => ccx.sess.bug("foreign_types_for_fn_ty called on non-function type")
     };
     let llsig = foreign_signature(ccx, &fn_sig, fn_sig.inputs);
-    let ret_def = !ty::type_is_voidish(ccx.tcx, fn_sig.output);
+    let ret_def = !return_type_is_void(ccx, fn_sig.output);
     let fn_ty = cabi::compute_abi_info(ccx,
                                        llsig.llarg_tys,
                                        llsig.llret_ty,
index 16a761a44db31f05055480aac6a3809c7d8402bd..ae03d48dbf0dc3d0d86e2ea5b97b150756a63af4 100644 (file)
 use middle::trans::adt;
 use middle::trans::base::*;
 use middle::trans::callee;
+use middle::trans::cleanup;
+use middle::trans::cleanup::CleanupMethods;
 use middle::trans::closure;
 use middle::trans::common::*;
-use middle::trans::datum::immediate_rvalue;
 use middle::trans::build::*;
 use middle::trans::expr;
 use middle::trans::machine::*;
@@ -108,22 +109,26 @@ fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
     }
 
     if field == abi::tydesc_field_take_glue && ty::type_is_boxed(t) {
-        return ty::mk_imm_box(tcx, ty::mk_nil());
+        return ty::mk_box(tcx, ty::mk_nil());
     }
 
     if field == abi::tydesc_field_drop_glue {
         match ty::get(t).sty {
             ty::ty_box(typ)
                 if !ty::type_needs_drop(tcx, typ) =>
-            return ty::mk_imm_box(tcx, ty::mk_nil()),
+            return ty::mk_box(tcx, ty::mk_nil()),
 
             ty::ty_vec(mt, ty::vstore_box)
                 if !ty::type_needs_drop(tcx, mt.ty) =>
-            return ty::mk_imm_box(tcx, ty::mk_nil()),
+            return ty::mk_box(tcx, ty::mk_nil()),
 
-            ty::ty_uniq(mt) | ty::ty_vec(mt, ty::vstore_uniq)
+            ty::ty_uniq(typ)
+                if !ty::type_needs_drop(tcx, typ) =>
+            return ty::mk_uniq(tcx, ty::mk_nil()),
+
+            ty::ty_vec(mt, ty::vstore_uniq)
                 if !ty::type_needs_drop(tcx, mt.ty) =>
-            return ty::mk_imm_uniq(tcx, ty::mk_nil()),
+            return ty::mk_uniq(tcx, ty::mk_nil()),
 
             _ => {}
         }
@@ -265,25 +270,23 @@ fn call_tydesc_glue<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t, field: uint)
 fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
                    -> &'a Block<'a> {
     let _icx = push_ctxt("make_visit_glue");
-    with_scope(bcx, None, "visitor cleanup", |bcx| {
-        let mut bcx = bcx;
-        let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx(),
-                                                                     ty::ReStatic) {
-            Ok(pair) => pair,
-            Err(s) => {
-                bcx.tcx().sess.fatal(s);
-            }
-        };
-        let v = PointerCast(bcx, v, type_of(bcx.ccx(), object_ty).ptr_to());
-        bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id);
-        // The visitor is a boxed object and needs to be dropped
-        add_clean(bcx, v, object_ty);
-        bcx
-    })
+    let mut bcx = bcx;
+    let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx(),
+                                                                 ty::ReStatic) {
+        Ok(pair) => pair,
+        Err(s) => {
+            bcx.tcx().sess.fatal(s);
+        }
+    };
+    let v = PointerCast(bcx, v, type_of(bcx.ccx(), object_ty).ptr_to());
+    bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id);
+    bcx
 }
 
-pub fn make_free_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
-                      -> &'a Block<'a> {
+pub fn make_free_glue<'a>(bcx: &'a Block<'a>,
+                          v: ValueRef,
+                          t: ty::t)
+                          -> &'a Block<'a> {
     // NB: v0 is an *alias* of type t here, not a direct value.
     let _icx = push_ctxt("make_free_glue");
     match ty::get(t).sty {
@@ -293,18 +296,13 @@ pub fn make_free_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
         let bcx = drop_ty(bcx, body, body_ty);
         trans_free(bcx, v)
       }
-      ty::ty_uniq(..) => {
-        let box_datum = immediate_rvalue(Load(bcx, v), t);
-        let not_null = IsNotNull(bcx, box_datum.val);
+      ty::ty_uniq(content_ty) => {
+        let llbox = Load(bcx, v);
+        let not_null = IsNotNull(bcx, llbox);
         with_cond(bcx, not_null, |bcx| {
-            let body_datum = box_datum.box_body(bcx);
-            let bcx = drop_ty(bcx, body_datum.to_ref_llval(bcx), body_datum.ty);
-            if ty::type_contents(bcx.tcx(), t).owns_managed() {
-                trans_free(bcx, box_datum.val)
-            } else {
-                trans_exchange_free(bcx, box_datum.val)
-            }
-        })
+                    let bcx = drop_ty(bcx, llbox, content_ty);
+                    trans_exchange_free(bcx, llbox)
+                })
       }
       ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) |
       ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
@@ -362,21 +360,24 @@ pub fn trans_struct_drop<'a>(
     // Be sure to put all of the fields 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 fails.
-    with_scope(bcx, None, "field drops", |bcx| {
-        let self_arg = PointerCast(bcx, v0, params[0]);
-        let args = ~[self_arg];
-
-        // Add all the fields as a value which needs to be cleaned at the end of
-        // this scope.
-        let field_tys = ty::struct_fields(bcx.tcx(), class_did, substs);
-        for (i, fld) in field_tys.iter().enumerate() {
-            let llfld_a = adt::trans_field_ptr(bcx, repr, v0, 0, i);
-            add_clean(bcx, llfld_a, fld.mt.ty);
-        }
+    let field_scope = bcx.fcx.push_custom_cleanup_scope();
+
+    let self_arg = PointerCast(bcx, v0, params[0]);
+    let args = ~[self_arg];
+
+    // Add all the fields as a value which needs to be cleaned at the end of
+    // this scope.
+    let field_tys = ty::struct_fields(bcx.tcx(), class_did, substs);
+    for (i, fld) in field_tys.iter().enumerate() {
+        let llfld_a = adt::trans_field_ptr(bcx, repr, v0, 0, i);
+        bcx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
+                                  llfld_a,
+                                  fld.mt.ty);
+    }
 
-        let (_, bcx) = invoke(bcx, dtor_addr, args, [], None);
-        bcx
-    })
+    let (_, bcx) = invoke(bcx, dtor_addr, args, [], None);
+
+    bcx.fcx.pop_and_trans_custom_cleanup_scope(bcx, field_scope)
 }
 
 pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
@@ -451,11 +452,13 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
 fn decr_refcnt_maybe_free<'a>(bcx: &'a Block<'a>, box_ptr_ptr: ValueRef,
                               t: Option<ty::t>) -> &'a Block<'a> {
     let _icx = push_ctxt("decr_refcnt_maybe_free");
+    let fcx = bcx.fcx;
     let ccx = bcx.ccx();
 
-    let decr_bcx = sub_block(bcx, "decr");
-    let free_bcx = sub_block(decr_bcx, "free");
-    let next_bcx = sub_block(bcx, "next");
+    let decr_bcx = fcx.new_temp_block("decr");
+    let free_bcx = fcx.new_temp_block("free");
+    let next_bcx = fcx.new_temp_block("next");
+
     let box_ptr = Load(bcx, box_ptr_ptr);
     let llnotnull = IsNotNull(bcx, box_ptr);
     CondBr(bcx, llnotnull, decr_bcx.llbb, next_bcx.llbb);
@@ -546,18 +549,6 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
                  ppaux::ty_to_str(ccx.tcx, t));
     }
 
-    let has_header = match ty::get(t).sty {
-        ty::ty_box(..) => true,
-        ty::ty_uniq(..) => ty::type_contents(ccx.tcx, t).owns_managed(),
-        _ => false
-    };
-
-    let borrow_offset = if has_header {
-        ccx.offsetof_gep(llty, [0u, abi::box_field_body])
-    } else {
-        C_uint(ccx, 0)
-    };
-
     let llsize = llsize_of(ccx, llty);
     let llalign = llalign_of(ccx, llty);
     let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
@@ -576,7 +567,6 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
         tydesc: gvar,
         size: llsize,
         align: llalign,
-        borrow_offset: borrow_offset,
         name: ty_name,
         take_glue: Cell::new(None),
         drop_glue: Cell::new(None),
@@ -592,7 +582,7 @@ fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
     let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, (~"glue_" + name)).to_managed();
     debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx, t));
     note_unique_llvm_symbol(ccx, fn_nm);
-    let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty);
+    let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty, ty::mk_nil());
     return llfn;
 }
 
@@ -606,7 +596,7 @@ fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef,
     let _s = StatRecorder::new(ccx, glue_name);
 
     let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None);
-    init_function(&fcx, false, ty::mk_nil(), None, None);
+    init_function(&fcx, false, ty::mk_nil(), None);
 
     lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
     ccx.stats.n_glues_created.set(ccx.stats.n_glues_created.get() + 1u);
@@ -686,15 +676,12 @@ pub fn emit_tydescs(ccx: &CrateContext) {
               }
             };
 
-        debug!("ti.borrow_offset: {}", ccx.tn.val_to_str(ti.borrow_offset));
-
         let tydesc = C_named_struct(ccx.tydesc_type,
                                     [ti.size, // size
                                      ti.align, // align
                                      take_glue, // take_glue
                                      drop_glue, // drop_glue
                                      visit_glue, // visit_glue
-                                     ti.borrow_offset, // borrow_offset
                                      ti.name]); // name
 
         unsafe {
index 7d0e5a435441b53e079a60052404e7997b70938d..98e3593a9f15f6f01d984a99010f9771b3f040ff 100644 (file)
@@ -178,7 +178,6 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
                        self_kind,
                        None,
                        mth.id,
-                       Some(&*mth),
                        []);
           }
           local_def(mth.id)
index 126aa9e7be580a2f45ab18c4097414d671cf4724..1fc749bb6876f734d39b5bd2b85e3ef12f4c70cb 100644 (file)
@@ -153,14 +153,14 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
 
     let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, item.id));
 
-    let fcx = new_fn_ctxt_w_id(ccx,
-                               path,
-                               decl,
-                               item.id,
-                               output_type,
-                               Some(substs),
-                               Some(item.span));
-    init_function(&fcx, true, output_type, Some(substs), None);
+    let fcx = new_fn_ctxt_detailed(ccx,
+                                   path,
+                                   decl,
+                                   item.id,
+                                   output_type,
+                                   Some(substs),
+                                   Some(item.span));
+    init_function(&fcx, true, output_type, Some(substs));
 
     set_always_inline(fcx.llfn);
 
@@ -254,27 +254,18 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
             let lltp_ty = type_of::type_of(ccx, tp_ty);
             Ret(bcx, C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty)));
         }
-        "move_val" => {
+        "move_val_init" => {
             // Create a datum reflecting the value being moved.
             // Use `appropriate_mode` so that the datum is by ref
             // if the value is non-immediate. Note that, with
             // intrinsics, there are no argument cleanups to
-            // concern ourselves with.
-            let tp_ty = substs.tys[0];
-            let mode = appropriate_mode(ccx, tp_ty);
-            let src = Datum {val: get_param(decl, first_real_arg + 1u),
-                             ty: tp_ty, mode: mode};
-            bcx = src.move_to(bcx, DROP_EXISTING,
-                              get_param(decl, first_real_arg));
-            RetVoid(bcx);
-        }
-        "move_val_init" => {
-            // See comments for `"move_val"`.
+            // concern ourselves with, so we can use an rvalue datum.
             let tp_ty = substs.tys[0];
-            let mode = appropriate_mode(ccx, tp_ty);
+            let mode = appropriate_rvalue_mode(ccx, tp_ty);
             let src = Datum {val: get_param(decl, first_real_arg + 1u),
-                             ty: tp_ty, mode: mode};
-            bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg));
+                             ty: tp_ty,
+                             kind: Rvalue(mode)};
+            bcx = src.store_to(bcx, get_param(decl, first_real_arg));
             RetVoid(bcx);
         }
         "min_align_of" => {
@@ -326,7 +317,7 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
         "uninit" => {
             // Do nothing, this is effectively a no-op
             let retty = substs.tys[0];
-            if type_is_immediate(ccx, retty) && !ty::type_is_nil(retty) {
+            if type_is_immediate(ccx, retty) && !return_type_is_void(ccx, retty) {
                 unsafe {
                     Ret(bcx, lib::llvm::llvm::LLVMGetUndef(type_of(ccx, retty).to_ref()));
                 }
@@ -365,7 +356,7 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
                                          pluralize(out_type_size)));
             }
 
-            if !ty::type_is_voidish(ccx.tcx, out_type) {
+            if !return_type_is_void(ccx, out_type) {
                 let llsrcval = get_param(decl, first_real_arg);
                 if type_is_immediate(ccx, in_type) {
                     match fcx.llretptr.get() {
@@ -431,9 +422,10 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
             // native function. There should be a general in-language
             // way to do this
             let llfty = type_of_rust_fn(bcx.ccx(), None, [], ty::mk_nil());
-            let morestack_addr = decl_cdecl_fn(
-                bcx.ccx().llmod, "__morestack", llfty);
-            let morestack_addr = PointerCast(bcx, morestack_addr, Type::nil().ptr_to());
+            let morestack_addr = decl_cdecl_fn(bcx.ccx().llmod, "__morestack",
+                                               llfty, ty::mk_nil());
+            let morestack_addr = PointerCast(bcx, morestack_addr,
+                                             Type::nil().ptr_to());
             Ret(bcx, morestack_addr);
         }
         "offset" => {
index f8aef908381189349342f8c93901c7bd318c5072..85b9e16e5cca117f8d4662a01155dc9de978a031 100644 (file)
@@ -18,6 +18,7 @@
 use middle::trans::build::*;
 use middle::trans::callee::*;
 use middle::trans::callee;
+use middle::trans::cleanup;
 use middle::trans::common::*;
 use middle::trans::datum::*;
 use middle::trans::expr::{SaveIn, Ignore};
@@ -132,7 +133,6 @@ pub fn trans_method(ccx: @CrateContext,
              self_ty,
              param_substs,
              method.id,
-             Some(method),
              []);
     llfn
 }
@@ -141,7 +141,8 @@ pub fn trans_method_callee<'a>(
                            bcx: &'a Block<'a>,
                            callee_id: ast::NodeId,
                            this: &ast::Expr,
-                           mentry: typeck::method_map_entry)
+                           mentry: typeck::method_map_entry,
+                           arg_cleanup_scope: cleanup::ScopeId)
                            -> Callee<'a> {
     let _icx = push_ctxt("impl::trans_method_callee");
 
@@ -153,9 +154,8 @@ pub fn trans_method_callee<'a>(
     match mentry.origin {
         typeck::method_static(did) => {
             let self_ty = monomorphize_type(bcx, mentry.self_ty);
-            let mut temp_cleanups = ~[];
             let Result {bcx, val} = trans_arg_expr(bcx, self_ty, this,
-                                                   &mut temp_cleanups,
+                                                   arg_cleanup_scope,
                                                    DontAutorefArg);
             // HACK should not need the pointer cast, eventually trans_fn_ref
             // should return a function type with the right type for self.
@@ -168,7 +168,6 @@ pub fn trans_method_callee<'a>(
                 data: Method(MethodData {
                     llfn: llfn_val,
                     llself: val,
-                    temp_cleanup: temp_cleanups.head_opt().map(|v| *v)
                 })
             }
         }
@@ -186,7 +185,8 @@ pub fn trans_method_callee<'a>(
 
                     let vtbl = find_vtable(bcx.tcx(), substs, p, b);
                     trans_monomorphized_callee(bcx, callee_id, this, mentry,
-                                               trait_id, off, vtbl)
+                                               trait_id, off, vtbl,
+                                               arg_cleanup_scope)
                 }
                 // how to get rid of this?
                 None => fail!("trans_method_callee: missing param_substs")
@@ -197,7 +197,8 @@ pub fn trans_method_callee<'a>(
             trans_trait_callee(bcx,
                                callee_id,
                                mt.real_index,
-                               this)
+                               this,
+                               arg_cleanup_scope)
         }
     }
 }
@@ -319,7 +320,8 @@ pub fn trans_monomorphized_callee<'a>(
                                   mentry: typeck::method_map_entry,
                                   trait_id: ast::DefId,
                                   n_method: uint,
-                                  vtbl: typeck::vtable_origin)
+                                  vtbl: typeck::vtable_origin,
+                                  arg_cleanup_scope: cleanup::ScopeId)
                                   -> Callee<'a> {
     let _icx = push_ctxt("impl::trans_monomorphized_callee");
     return match vtbl {
@@ -330,9 +332,8 @@ pub fn trans_monomorphized_callee<'a>(
 
           // obtain the `self` value:
           let self_ty = monomorphize_type(bcx, mentry.self_ty);
-          let mut temp_cleanups = ~[];
           let Result {bcx, val} = trans_arg_expr(bcx, self_ty, base,
-                                                 &mut temp_cleanups,
+                                                 arg_cleanup_scope,
                                                  DontAutorefArg);
 
           // create a concatenated set of substitutions which includes
@@ -361,7 +362,6 @@ pub fn trans_monomorphized_callee<'a>(
               data: Method(MethodData {
                   llfn: llfn_val,
                   llself: val,
-                  temp_cleanup: temp_cleanups.head_opt().map(|v| *v)
               })
           }
       }
@@ -425,7 +425,8 @@ pub fn trans_trait_callee<'a>(
                           bcx: &'a Block<'a>,
                           callee_id: ast::NodeId,
                           n_method: uint,
-                          self_expr: &ast::Expr)
+                          self_expr: &ast::Expr,
+                          arg_cleanup_scope: cleanup::ScopeId)
                           -> Callee<'a> {
     /*!
      * Create a method callee where the method is coming from a trait
@@ -439,38 +440,31 @@ pub fn trans_trait_callee<'a>(
     let _icx = push_ctxt("impl::trans_trait_callee");
     let mut bcx = bcx;
 
-    // make a local copy for trait if needed
-    let self_ty = expr_ty_adjusted(bcx, self_expr);
-    let self_scratch = match ty::get(self_ty).sty {
-        ty::ty_trait(_, _, ty::RegionTraitStore(..), _, _) => {
-            unpack_datum!(bcx, expr::trans_to_datum(bcx, self_expr))
-        }
-        _ => {
-            let d = scratch_datum(bcx, self_ty, "__trait_callee", false);
-            bcx = expr::trans_into(bcx, self_expr, expr::SaveIn(d.val));
-            // Arrange a temporary cleanup for the object in case something
-            // should go wrong before the method is actually *invoked*.
-            d.add_clean(bcx);
-            d
-        }
-    };
+    // Translate self_datum and take ownership of the value by
+    // converting to an rvalue.
+    let self_datum = unpack_datum!(
+        bcx, expr::trans(bcx, self_expr));
+    let self_datum = unpack_datum!(
+        bcx, self_datum.to_rvalue_datum(bcx, "trait_callee"));
+
+    // Convert to by-ref since `trans_trait_callee_from_llval` wants it
+    // that way.
+    let self_datum = unpack_datum!(
+        bcx, self_datum.to_ref_datum(bcx));
 
+    // Arrange cleanup in case something should go wrong before the
+    // actual call occurs.
+    let llval = self_datum.add_clean(bcx.fcx, arg_cleanup_scope);
 
     let callee_ty = node_id_type(bcx, callee_id);
-    trans_trait_callee_from_llval(bcx,
-                                  callee_ty,
-                                  n_method,
-                                  self_scratch.val,
-                                  Some(self_scratch.val))
+    trans_trait_callee_from_llval(bcx, callee_ty, n_method, llval)
 }
 
-pub fn trans_trait_callee_from_llval<'a>(
-                                     bcx: &'a Block<'a>,
-                                     callee_ty: ty::t,
-                                     n_method: uint,
-                                     llpair: ValueRef,
-                                     temp_cleanup: Option<ValueRef>)
-                                     -> Callee<'a> {
+pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
+                                         callee_ty: ty::t,
+                                         n_method: uint,
+                                         llpair: ValueRef)
+                                         -> Callee<'a> {
     /*!
      * Same as `trans_trait_callee()` above, except that it is given
      * a by-ref pointer to the object pair.
@@ -501,7 +495,6 @@ pub fn trans_trait_callee_from_llval<'a>(
         data: Method(MethodData {
             llfn: mptr,
             llself: llself,
-            temp_cleanup: temp_cleanup
         })
     };
 }
@@ -632,41 +625,38 @@ fn emit_vtable_methods(bcx: &Block,
     })
 }
 
-pub fn trans_trait_cast<'a>(
-                        bcx: &'a Block<'a>,
-                        val: &ast::Expr,
-                        id: ast::NodeId,
-                        dest: expr::Dest,
-                        obj: Option<Datum>)
-                        -> &'a Block<'a> {
+pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
+                            datum: Datum<Expr>,
+                            id: ast::NodeId,
+                            dest: expr::Dest)
+                            -> &'a Block<'a> {
+    /*!
+     * Generates the code to convert from a pointer (`~T`, `&T`, etc)
+     * into an object (`~Trait`, `&Trait`, etc). This means creating a
+     * pair where the first word is the vtable and the second word is
+     * the pointer.
+     */
+
     let mut bcx = bcx;
     let _icx = push_ctxt("impl::trans_cast");
 
     let lldest = match dest {
         Ignore => {
-            return expr::trans_into(bcx, val, Ignore);
+            return datum.clean(bcx, "trait_cast", id);
         }
         SaveIn(dest) => dest
     };
 
     let ccx = bcx.ccx();
-    let v_ty = expr_ty(bcx, val);
+    let v_ty = datum.ty;
+    let llbox_ty = type_of(bcx.ccx(), datum.ty);
 
+    // Store the pointer into the first half of pair.
     let mut llboxdest = GEPi(bcx, lldest, [0u, abi::trt_field_box]);
-    // Just store the pointer into the pair. (Region/borrowed
-    // and boxed trait objects are represented as pairs, and
-    // have no type descriptor field.)
-    llboxdest = PointerCast(bcx,
-                            llboxdest,
-                            type_of(bcx.ccx(), v_ty).ptr_to());
-    bcx = match obj {
-        Some(datum) => {
-            datum.store_to_dest(bcx, SaveIn(llboxdest))
-        }
-        None => expr::trans_into(bcx, val, SaveIn(llboxdest))
-    };
+    llboxdest = PointerCast(bcx, llboxdest, llbox_ty.ptr_to());
+    bcx = datum.store_to(bcx, llboxdest);
 
-    // Store the vtable into the pair or triple.
+    // Store the vtable into the second half of pair.
     // This is structured a bit funny because of dynamic borrow failures.
     let origins = {
         let res = {
@@ -677,9 +667,9 @@ pub fn trans_trait_cast<'a>(
         res[0]
     };
     let vtable = get_vtable(bcx, v_ty, origins);
-    Store(bcx, vtable, PointerCast(bcx,
-                                   GEPi(bcx, lldest, [0u, abi::trt_field_vtable]),
-                                   val_ty(vtable).ptr_to()));
+    let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]);
+    let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
+    Store(bcx, vtable, llvtabledest);
 
     bcx
 }
index e534e087cb835f590ca2618e72c5ead5290971ce..7ac491edfeb2a82cf883b7d8ef8300beb56aafc4 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+pub mod doc;
 pub mod macros;
 pub mod inline;
 pub mod monomorphize;
@@ -44,3 +45,4 @@
 pub mod value;
 pub mod basic_block;
 pub mod llrepr;
+pub mod cleanup;
index a05ca4296b1301c0afd44f8cdcf85bbece6d2db2..a128a953eacff7032fba919df8d4a7514fbda9fa 100644 (file)
@@ -238,7 +238,6 @@ pub fn monomorphic_fn(ccx: @CrateContext,
                          None,
                          Some(psubsts),
                          fn_id.node,
-                         None,
                          []);
                 d
             }
index ef9f48d478531e4da956cc5d551b18e464c77ae4..c13bb139da759482736df9793ddd8504307734d5 100644 (file)
@@ -61,7 +61,7 @@ pub fn c_slice(&mut self, s: @str) -> ValueRef {
         let bcx = self.bcx;
         let str_vstore = ty::vstore_slice(ty::ReStatic);
         let str_ty = ty::mk_str(bcx.tcx(), str_vstore);
-        let scratch = scratch_datum(bcx, str_ty, "", false);
+        let scratch = rvalue_scratch_datum(bcx, str_ty, "");
         let len = C_uint(bcx.ccx(), s.len());
         let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), Type::i8p());
         Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ]));
@@ -90,6 +90,7 @@ pub fn c_mt(&mut self, mt: &ty::mt) -> ~[ValueRef] {
     }
 
     pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
+        let fcx = self.bcx.fcx;
         let tcx = self.bcx.tcx();
         let mth_idx = ty::method_idx(
             tcx.sess.ident_of(~"visit_" + ty_name),
@@ -106,14 +107,13 @@ pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
         let bool_ty = ty::mk_bool();
         let result = unpack_result!(bcx, callee::trans_call_inner(
             self.bcx, None, mth_ty, bool_ty,
-            |bcx| meth::trans_trait_callee_from_llval(bcx,
-                                                      mth_ty,
-                                                      mth_idx,
-                                                      v,
-                                                      None),
+            |bcx, _| meth::trans_trait_callee_from_llval(bcx,
+                                                         mth_ty,
+                                                         mth_idx,
+                                                         v),
             ArgVals(args), None, DontAutorefArg));
         let result = bool_to_i1(bcx, result);
-        let next_bcx = sub_block(bcx, "next");
+        let next_bcx = fcx.new_temp_block("next");
         CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb);
         self.bcx = next_bcx
     }
@@ -176,6 +176,7 @@ pub fn visit_ty(&mut self, t: ty::t) {
               self.visit("vec", values)
           }
 
+          // Should rename to str_*/vec_*.
           ty::ty_str(vst) => {
               let (name, extra) = self.vstore_name_and_extra(t, vst);
               self.visit(~"estr_" + name, extra)
@@ -183,12 +184,9 @@ pub fn visit_ty(&mut self, t: ty::t) {
           ty::ty_vec(ref mt, vst) => {
               let (name, extra) = self.vstore_name_and_extra(t, vst);
               let extra = extra + self.c_mt(mt);
-              if "uniq" == name && ty::type_contents(bcx.tcx(), t).owns_managed() {
-                  self.visit("evec_uniq_managed", extra)
-              } else {
-                  self.visit(~"evec_" + name, extra)
-              }
+              self.visit(~"evec_" + name, extra)
           }
+          // Should remove mt from box and uniq.
           ty::ty_box(typ) => {
               let extra = self.c_mt(&ty::mt {
                   ty: typ,
@@ -196,13 +194,12 @@ pub fn visit_ty(&mut self, t: ty::t) {
               });
               self.visit("box", extra)
           }
-          ty::ty_uniq(ref mt) => {
-              let extra = self.c_mt(mt);
-              if ty::type_contents(bcx.tcx(), t).owns_managed() {
-                  self.visit("uniq_managed", extra)
-              } else {
-                  self.visit("uniq", extra)
-              }
+          ty::ty_uniq(typ) => {
+              let extra = self.c_mt(&ty::mt {
+                  ty: typ,
+                  mutbl: ast::MutImmutable,
+              });
+              self.visit("uniq", extra)
           }
           ty::ty_ptr(ref mt) => {
               let extra = self.c_mt(mt);
@@ -301,7 +298,7 @@ pub fn visit_ty(&mut self, t: ty::t) {
                                       llfdecl,
                                       ty::mk_u64(),
                                       None);
-                init_function(&fcx, false, ty::mk_u64(), None, None);
+                init_function(&fcx, false, ty::mk_u64(), None);
 
                 let arg = unsafe {
                     //
@@ -311,13 +308,13 @@ pub fn visit_ty(&mut self, t: ty::t) {
                     //
                     llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint)
                 };
-                let mut bcx = fcx.entry_bcx.get().unwrap();
+                let bcx = fcx.entry_bcx.get().unwrap();
                 let arg = BitCast(bcx, arg, llptrty);
                 let ret = adt::trans_get_discr(bcx, repr, arg, Some(Type::i64()));
                 Store(bcx, ret, fcx.llretptr.get().unwrap());
                 match fcx.llreturn.get() {
-                    Some(llreturn) => cleanup_and_Br(bcx, bcx, llreturn),
-                    None => bcx = cleanup_block(bcx, Some(bcx.llbb))
+                    Some(llreturn) => Br(bcx, llreturn),
+                    None => {}
                 };
                 finish_fn(&fcx, bcx);
                 llfdecl
@@ -392,7 +389,8 @@ pub fn emit_calls_to_trait_visit_ty<'a>(
                                     visitor_val: ValueRef,
                                     visitor_trait_id: DefId)
                                     -> &'a Block<'a> {
-    let final = sub_block(bcx, "final");
+    let fcx = bcx.fcx;
+    let final = fcx.new_temp_block("final");
     let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx).unwrap();
     let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
     let mut r = Reflector {
index ce7a2a6ec68dcfbe93be73db1ecc70cedd483c0a..1642d333a9a6097d4b189e0e7e820255477544a7 100644 (file)
@@ -17,6 +17,8 @@
 use middle::trans::base;
 use middle::trans::build::*;
 use middle::trans::callee;
+use middle::trans::cleanup;
+use middle::trans::cleanup::CleanupMethods;
 use middle::trans::common::*;
 use middle::trans::datum::*;
 use middle::trans::expr::{Dest, Ignore, SaveIn};
@@ -26,7 +28,6 @@
 use middle::trans::type_::Type;
 use middle::trans::type_of;
 use middle::ty;
-use util::common::indenter;
 use util::ppaux::ty_to_str;
 
 use syntax::ast;
@@ -39,14 +40,14 @@ pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
     let unit_ty = ty::sequence_element_type(tcx, t);
     let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty);
     match ty::get(t).sty {
-      ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) => {
-        ty::mk_imm_uniq(tcx, unboxed_vec_ty)
-      }
-      ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => {
-        ty::mk_imm_box(tcx, unboxed_vec_ty)
-      }
-      _ => tcx.sess.bug("non boxed-vec type \
-                         in tvec::expand_boxed_vec_ty")
+        ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) => {
+            ty::mk_uniq(tcx, unboxed_vec_ty)
+        }
+        ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => {
+            ty::mk_box(tcx, unboxed_vec_ty)
+        }
+        _ => tcx.sess.bug("non boxed-vec type \
+                           in tvec::expand_boxed_vec_ty")
     }
 }
 
@@ -64,7 +65,14 @@ pub fn get_alloc(bcx: &Block, vptr: ValueRef) -> ValueRef {
 }
 
 pub fn get_bodyptr(bcx: &Block, vptr: ValueRef, t: ty::t) -> ValueRef {
-    if ty::type_contents(bcx.tcx(), t).owns_managed() {
+    let vt = vec_types(bcx, t);
+
+    let managed = match ty::get(vt.vec_ty).sty {
+      ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => true,
+      _ => false
+    };
+
+    if managed {
         GEPi(bcx, vptr, [0u, abi::box_field_body])
     } else {
         vptr
@@ -106,7 +114,6 @@ pub fn alloc_raw<'a>(
             base::malloc_general_dyn(bcx, vecbodyty, heap, vecsize);
         Store(bcx, fill, GEPi(bcx, body, [0u, abi::vec_elt_fill]));
         Store(bcx, alloc, GEPi(bcx, body, [0u, abi::vec_elt_alloc]));
-        base::maybe_set_managed_unique_rc(bcx, bx, heap);
         return rslt(bcx, bx);
     }
 }
@@ -117,7 +124,7 @@ pub fn alloc_uniq_raw<'a>(
                       fill: ValueRef,
                       alloc: ValueRef)
                       -> Result<'a> {
-    alloc_raw(bcx, unit_ty, fill, alloc, base::heap_for_unique(bcx, unit_ty))
+    alloc_raw(bcx, unit_ty, fill, alloc, heap_exchange)
 }
 
 pub fn alloc_vec<'a>(
@@ -187,7 +194,6 @@ pub fn trans_fixed_vstore<'a>(
 
     debug!("trans_fixed_vstore(vstore_expr={}, dest={:?})",
            bcx.expr_to_str(vstore_expr), dest.to_str(bcx.ccx()));
-    let _indenter = indenter();
 
     let vt = vec_types_from_expr(bcx, vstore_expr);
 
@@ -208,17 +214,18 @@ pub fn trans_slice_vstore<'a>(
                           content_expr: &ast::Expr,
                           dest: expr::Dest)
                           -> &'a Block<'a> {
-    //!
-    //
-    // &[...] allocates memory on the stack and writes the values into it,
-    // returning a slice (pair of ptr, len).  &"..." is similar except that
-    // the memory can be statically allocated.
-
-    let ccx = bcx.ccx();
+    /*!
+     * &[...] allocates memory on the stack and writes the values into it,
+     * returning a slice (pair of ptr, len).  &"..." is similar except that
+     * the memory can be statically allocated.
+     */
+
+    let fcx = bcx.fcx;
+    let ccx = fcx.ccx;
+    let mut bcx = bcx;
 
     debug!("trans_slice_vstore(vstore_expr={}, dest={})",
            bcx.expr_to_str(vstore_expr), dest.to_str(ccx));
-    let _indenter = indenter();
 
     // Handle the &"..." case:
     match content_expr.node {
@@ -238,21 +245,29 @@ pub fn trans_slice_vstore<'a>(
     let count = elements_required(bcx, content_expr);
     debug!("vt={}, count={:?}", vt.to_str(ccx), count);
 
-    // Make a fixed-length backing array and allocate it on the stack.
     let llcount = C_uint(ccx, count);
-    let llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
-
-    // Arrange for the backing array to be cleaned up.
-    let fixed_ty = ty::mk_vec(bcx.tcx(),
-                              ty::mt {ty: vt.unit_ty, mutbl: ast::MutMutable},
-                              ty::vstore_fixed(count));
-    let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
-    let llfixed_casted = BitCast(bcx, llfixed, llfixed_ty);
-    add_clean(bcx, llfixed_casted, fixed_ty);
-
-    // Generate the content into the backing array.
-    let bcx = write_content(bcx, &vt, vstore_expr,
+    let llfixed;
+    if count == 0 {
+        // Zero-length array: just use NULL as the data pointer
+        llfixed = C_null(vt.llunit_ty.ptr_to());
+    } else {
+        // Make a fixed-length backing array and allocate it on the stack.
+        llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
+
+        // Arrange for the backing array to be cleaned up.
+        let fixed_ty = ty::mk_vec(bcx.tcx(),
+                                  ty::mt {ty: vt.unit_ty,
+                                          mutbl: ast::MutMutable},
+                                  ty::vstore_fixed(count));
+        let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
+        let llfixed_casted = BitCast(bcx, llfixed, llfixed_ty);
+        let cleanup_scope = cleanup::temporary_scope(bcx.tcx(), content_expr.id);
+        fcx.schedule_drop_mem(cleanup_scope, llfixed_casted, fixed_ty);
+
+        // Generate the content into the backing array.
+        bcx = write_content(bcx, &vt, vstore_expr,
                             content_expr, SaveIn(llfixed));
+    }
 
     // Finally, create the slice pair itself.
     match dest {
@@ -272,16 +287,15 @@ pub fn trans_lit_str<'a>(
                      str_lit: @str,
                      dest: Dest)
                      -> &'a Block<'a> {
-    //!
-    //
-    // Literal strings translate to slices into static memory.  This is
-    // different from trans_slice_vstore() above because it does need to copy
-    // the content anywhere.
+    /*!
+     * Literal strings translate to slices into static memory.  This is
+     * different from trans_slice_vstore() above because it does need to copy
+     * the content anywhere.
+     */
 
     debug!("trans_lit_str(lit_expr={}, dest={})",
            bcx.expr_to_str(lit_expr),
            dest.to_str(bcx.ccx()));
-    let _indenter = indenter();
 
     match dest {
         Ignore => bcx,
@@ -302,20 +316,19 @@ pub fn trans_lit_str<'a>(
 }
 
 
-pub fn trans_uniq_or_managed_vstore<'a>(
-                                    bcx: &'a Block<'a>,
-                                    heap: heap,
-                                    vstore_expr: &ast::Expr,
-                                    content_expr: &ast::Expr)
-                                    -> DatumBlock<'a> {
-    //!
-    //
-    // @[...] or ~[...] (also @"..." or ~"...") allocate boxes in the
-    // appropriate heap and write the array elements into them.
+pub fn trans_uniq_or_managed_vstore<'a>(bcx: &'a Block<'a>,
+                                        heap: heap,
+                                        vstore_expr: &ast::Expr,
+                                        content_expr: &ast::Expr)
+                                        -> DatumBlock<'a, Expr> {
+    /*!
+     * @[...] or ~[...] (also @"..." or ~"...") allocate boxes in the
+     * appropriate heap and write the array elements into them.
+     */
 
     debug!("trans_uniq_or_managed_vstore(vstore_expr={}, heap={:?})",
            bcx.expr_to_str(vstore_expr), heap);
-    let _indenter = indenter();
+    let fcx = bcx.fcx;
 
     // Handle ~"".
     match heap {
@@ -328,7 +341,7 @@ pub fn trans_uniq_or_managed_vstore<'a>(
                             let llptrval = PointerCast(bcx, llptrval, Type::i8p());
                             let llsizeval = C_uint(bcx.ccx(), s.len());
                             let typ = ty::mk_str(bcx.tcx(), ty::vstore_uniq);
-                            let lldestval = scratch_datum(bcx, typ, "", false);
+                            let lldestval = rvalue_scratch_datum(bcx, typ, "");
                             let alloc_fn = langcall(bcx,
                                                     Some(lit.span),
                                                     "",
@@ -337,11 +350,8 @@ pub fn trans_uniq_or_managed_vstore<'a>(
                                 bcx,
                                 alloc_fn,
                                 [ llptrval, llsizeval ],
-                                Some(expr::SaveIn(lldestval.to_ref_llval(bcx)))).bcx;
-                            return DatumBlock {
-                                bcx: bcx,
-                                datum: lldestval
-                            };
+                                Some(expr::SaveIn(lldestval.val))).bcx;
+                            return DatumBlock(bcx, lldestval).to_expr_datumblock();
                         }
                         _ => {}
                     }
@@ -350,7 +360,7 @@ pub fn trans_uniq_or_managed_vstore<'a>(
             }
         }
         heap_exchange_closure => fail!("vectors use exchange_alloc"),
-        heap_managed | heap_managed_unique => {}
+        heap_managed => {}
     }
 
     let vt = vec_types_from_expr(bcx, vstore_expr);
@@ -358,7 +368,11 @@ pub fn trans_uniq_or_managed_vstore<'a>(
 
     let Result {bcx, val} = alloc_vec(bcx, vt.unit_ty, count, heap);
 
-    add_clean_free(bcx, val, heap);
+    // Create a temporary scope lest execution should fail while
+    // constructing the vector.
+    let temp_scope = fcx.push_custom_cleanup_scope();
+    fcx.schedule_free_value(cleanup::CustomScope(temp_scope), val, heap);
+
     let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val, vt.vec_ty));
 
     debug!("alloc_vec() returned val={}, dataptr={}",
@@ -367,9 +381,9 @@ pub fn trans_uniq_or_managed_vstore<'a>(
     let bcx = write_content(bcx, &vt, vstore_expr,
                             content_expr, SaveIn(dataptr));
 
-    revoke_clean(bcx, val);
+    fcx.pop_custom_cleanup_scope(temp_scope);
 
-    return immediate_rvalue_bcx(bcx, val, vt.vec_ty);
+    return immediate_rvalue_bcx(bcx, val, vt.vec_ty).to_expr_datumblock();
 }
 
 pub fn write_content<'a>(
@@ -380,13 +394,13 @@ pub fn write_content<'a>(
                      dest: Dest)
                      -> &'a Block<'a> {
     let _icx = push_ctxt("tvec::write_content");
+    let fcx = bcx.fcx;
     let mut bcx = bcx;
 
     debug!("write_content(vt={}, dest={}, vstore_expr={:?})",
            vt.to_str(bcx.ccx()),
            dest.to_str(bcx.ccx()),
            bcx.expr_to_str(vstore_expr));
-    let _indenter = indenter();
 
     match content_expr.node {
         ast::ExprLit(lit) => {
@@ -424,19 +438,19 @@ pub fn write_content<'a>(
                 }
 
                 SaveIn(lldest) => {
-                    let mut temp_cleanups = ~[];
+                    let temp_scope = fcx.push_custom_cleanup_scope();
                     for (i, element) in elements.iter().enumerate() {
                         let lleltptr = GEPi(bcx, lldest, [i]);
                         debug!("writing index {:?} with lleltptr={:?}",
                                i, bcx.val_to_str(lleltptr));
                         bcx = expr::trans_into(bcx, *element,
                                                SaveIn(lleltptr));
-                        add_clean_temp_mem(bcx, lleltptr, vt.unit_ty);
-                        temp_cleanups.push(lleltptr);
-                    }
-                    for cleanup in temp_cleanups.iter() {
-                        revoke_clean(bcx, *cleanup);
+                        fcx.schedule_drop_mem(
+                            cleanup::CustomScope(temp_scope),
+                            lleltptr,
+                            vt.unit_ty);
                     }
+                    fcx.pop_custom_cleanup_scope(temp_scope);
                 }
             }
             return bcx;
@@ -457,14 +471,16 @@ pub fn write_content<'a>(
                     // this can only happen as a result of OOM. So we just skip out on the
                     // cleanup since things would *probably* be broken at that point anyways.
 
-                    let elem = unpack_datum!(bcx, {
-                        expr::trans_to_datum(bcx, element)
-                    });
+                    let elem = unpack_datum!(bcx, expr::trans(bcx, element));
+                    assert!(!ty::type_moves_by_default(bcx.tcx(), elem.ty));
 
-                    iter_vec_loop(bcx, lldest, vt,
+                    let bcx = iter_vec_loop(bcx, lldest, vt,
                                   C_uint(bcx.ccx(), count), |set_bcx, lleltptr, _| {
-                        elem.copy_to(set_bcx, INIT, lleltptr)
-                    })
+                        elem.shallow_copy_and_take(set_bcx, lleltptr)
+                    });
+
+                    elem.add_clean_if_rvalue(bcx, element.id);
+                    bcx
                 }
             }
         }
@@ -516,15 +532,16 @@ pub fn elements_required(bcx: &Block, content_expr: &ast::Expr) -> uint {
     }
 }
 
-pub fn get_base_and_byte_len(bcx: &Block, llval: ValueRef, vec_ty: ty::t)
+pub fn get_base_and_byte_len(bcx: &Block,
+                             llval: ValueRef,
+                             vec_ty: ty::t)
                              -> (ValueRef, ValueRef) {
-    //!
-    //
-    // Converts a vector into the slice pair.  The vector should be stored in
-    // `llval` which should be either immediate or by-ref as appropriate for
-    // the vector type.  If you have a datum, you would probably prefer to
-    // call `Datum::get_base_and_byte_len()` which will handle any conversions for
-    // you.
+    /*!
+     * Converts a vector into the slice pair.  The vector should be
+     * stored in `llval` which should be by ref. If you have a datum,
+     * you would probably prefer to call
+     * `Datum::get_base_and_byte_len()`.
+     */
 
     let ccx = bcx.ccx();
     let vt = vec_types(bcx, vec_ty);
@@ -541,27 +558,32 @@ pub fn get_base_and_byte_len(bcx: &Block, llval: ValueRef, vec_ty: ty::t)
             (base, len)
         }
         ty::vstore_slice(_) => {
+            assert!(!type_is_immediate(bcx.ccx(), vt.vec_ty));
             let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
             let count = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
             let len = Mul(bcx, count, vt.llunit_size);
             (base, len)
         }
         ty::vstore_uniq | ty::vstore_box => {
+            assert!(type_is_immediate(bcx.ccx(), vt.vec_ty));
+            let llval = Load(bcx, llval);
             let body = get_bodyptr(bcx, llval, vec_ty);
             (get_dataptr(bcx, body), get_fill(bcx, body))
         }
     }
 }
 
-pub fn get_base_and_len(bcx: &Block, llval: ValueRef, vec_ty: ty::t)
+pub fn get_base_and_len(bcx: &Block,
+                        llval: ValueRef,
+                        vec_ty: ty::t)
                         -> (ValueRef, ValueRef) {
-    //!
-    //
-    // Converts a vector into the slice pair.  The vector should be stored in
-    // `llval` which should be either immediate or by-ref as appropriate for
-    // the vector type.  If you have a datum, you would probably prefer to
-    // call `Datum::get_base_and_len()` which will handle any conversions for
-    // you.
+    /*!
+     * Converts a vector into the slice pair.  The vector should be
+     * stored in `llval` which should be by-reference.  If you have a
+     * datum, you would probably prefer to call
+     * `Datum::get_base_and_len()` which will handle any conversions
+     * for you.
+     */
 
     let ccx = bcx.ccx();
     let vt = vec_types(bcx, vec_ty);
@@ -577,11 +599,14 @@ pub fn get_base_and_len(bcx: &Block, llval: ValueRef, vec_ty: ty::t)
             (base, C_uint(ccx, n))
         }
         ty::vstore_slice(_) => {
+            assert!(!type_is_immediate(bcx.ccx(), vt.vec_ty));
             let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
             let count = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
             (base, count)
         }
         ty::vstore_uniq | ty::vstore_box => {
+            assert!(type_is_immediate(bcx.ccx(), vt.vec_ty));
+            let llval = Load(bcx, llval);
             let body = get_bodyptr(bcx, llval, vec_ty);
             (get_dataptr(bcx, body), UDiv(bcx, get_fill(bcx, body), vt.llunit_size))
         }
@@ -600,12 +625,13 @@ pub fn iter_vec_loop<'r,
                      f: iter_vec_block<'r,'b>)
                      -> &'b Block<'b> {
     let _icx = push_ctxt("tvec::iter_vec_loop");
+    let fcx = bcx.fcx;
 
-    let next_bcx = sub_block(bcx, "iter_vec_loop: while next");
-    let loop_bcx = loop_scope_block(bcx, next_bcx, None, "iter_vec_loop", None);
-    let cond_bcx = scope_block(loop_bcx, None, "iter_vec_loop: loop cond");
-    let body_bcx = scope_block(loop_bcx, None, "iter_vec_loop: body: main");
-    let inc_bcx = scope_block(loop_bcx, None, "iter_vec_loop: loop inc");
+    let next_bcx = fcx.new_temp_block("expr_repeat: while next");
+    let loop_bcx = fcx.new_temp_block("expr_repeat");
+    let cond_bcx = fcx.new_temp_block("expr_repeat: loop cond");
+    let body_bcx = fcx.new_temp_block("expr_repeat: body: set");
+    let inc_bcx = fcx.new_temp_block("expr_repeat: body: inc");
     Br(bcx, loop_bcx.llbb);
 
     let loop_counter = {
@@ -657,6 +683,7 @@ pub fn iter_vec_raw<'r,
                     f: iter_vec_block<'r,'b>)
                     -> &'b Block<'b> {
     let _icx = push_ctxt("tvec::iter_vec_raw");
+    let fcx = bcx.fcx;
 
     let vt = vec_types(bcx, vec_ty);
     if (vt.llunit_alloc_size == 0) {
@@ -670,14 +697,14 @@ pub fn iter_vec_raw<'r,
         let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
 
         // Now perform the iteration.
-        let header_bcx = base::sub_block(bcx, "iter_vec_loop_header");
+        let header_bcx = fcx.new_temp_block("iter_vec_loop_header");
         Br(bcx, header_bcx.llbb);
         let data_ptr =
             Phi(header_bcx, val_ty(data_ptr), [data_ptr], [bcx.llbb]);
         let not_yet_at_end =
             ICmp(header_bcx, lib::llvm::IntULT, data_ptr, data_end_ptr);
-        let body_bcx = base::sub_block(header_bcx, "iter_vec_loop_body");
-        let next_bcx = base::sub_block(header_bcx, "iter_vec_next");
+        let body_bcx = fcx.new_temp_block("iter_vec_loop_body");
+        let next_bcx = fcx.new_temp_block("iter_vec_next");
         CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb);
         let body_bcx = f(body_bcx, data_ptr, vt.unit_ty);
         AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr,
@@ -685,7 +712,6 @@ pub fn iter_vec_raw<'r,
                          body_bcx.llbb);
         Br(body_bcx, header_bcx.llbb);
         next_bcx
-
     }
 }
 
index d4ba4a76f81290bf78392a70f6c3083e06f23e4c..833a7848ad316a0f16cc11e34d9eb43ce58ba819 100644 (file)
@@ -220,7 +220,6 @@ pub fn tydesc(arch: Architecture) -> Type {
                      glue_fn_ty, // take
                      glue_fn_ty, // drop
                      glue_fn_ty, // visit
-                     int_ty, // borrow_offset
                      Type::struct_([Type::i8p(), Type::int(arch)], false)]; // name
         tydesc.set_struct_body(elems, false);
 
@@ -269,10 +268,6 @@ pub fn opaque_box(ctx: &CrateContext) -> Type {
         Type::smart_ptr(ctx, &Type::opaque())
     }
 
-    pub fn unique(ctx: &CrateContext, ty: &Type) -> Type {
-        Type::smart_ptr(ctx, ty)
-    }
-
     pub fn opaque_cbox_ptr(cx: &CrateContext) -> Type {
         Type::opaque_box(cx).ptr_to()
     }
@@ -281,7 +276,7 @@ pub fn opaque_trait(ctx: &CrateContext, store: ty::TraitStore) -> Type {
         let tydesc_ptr = ctx.tydesc_type.ptr_to();
         let box_ty = match store {
             ty::BoxTraitStore => Type::opaque_box(ctx),
-            ty::UniqTraitStore => Type::unique(ctx, &Type::i8()),
+            ty::UniqTraitStore => Type::i8(),
             ty::RegionTraitStore(..) => Type::i8()
         };
         Type::struct_([tydesc_ptr, box_ty.ptr_to()], false)
index f59c2acd0274c9e66f2cbcb7f79c119e3042396b..4db89fbeccec7497d20f810f66edf8a4efeb6a8c 100644 (file)
@@ -68,10 +68,10 @@ pub fn type_of_rust_fn(cx: &CrateContext,
     atys.push_all(type_of_explicit_args(cx, inputs));
 
     // Use the output as the actual return value if it's immediate.
-    if !use_out_pointer && !ty::type_is_voidish(cx.tcx, output) {
-        Type::func(atys, &lloutputtype)
-    } else {
+    if use_out_pointer || return_type_is_void(cx, output) {
         Type::func(atys, &Type::void())
+    } else {
+        Type::func(atys, &lloutputtype)
     }
 }
 
@@ -244,22 +244,12 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
           let ty = type_of(cx, typ);
           Type::smart_ptr(cx, &ty).ptr_to()
       }
-      ty::ty_uniq(ref mt) => {
-          let ty = type_of(cx, mt.ty);
-          if ty::type_contents(cx.tcx, mt.ty).owns_managed() {
-              Type::unique(cx, &ty).ptr_to()
-          } else {
-              ty.ptr_to()
-          }
+      ty::ty_uniq(typ) => {
+          type_of(cx, typ).ptr_to()
       }
       ty::ty_vec(ref mt, ty::vstore_uniq) => {
           let ty = type_of(cx, mt.ty);
-          let ty = Type::vec(cx.sess.targ_cfg.arch, &ty);
-          if ty::type_contents(cx.tcx, mt.ty).owns_managed() {
-              Type::unique(cx, &ty).ptr_to()
-          } else {
-              ty.ptr_to()
-          }
+          Type::vec(cx.sess.targ_cfg.arch, &ty).ptr_to()
       }
       ty::ty_unboxed_vec(ref mt) => {
           let ty = type_of(cx, mt.ty);
index b3d467661e8d361e0a0b4061d54eafd7c95e2dcb..5b310feb58db50f9a2f268469d81bc7a2296ef7b 100644 (file)
@@ -8,27 +8,25 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Logic relating to rooting and write guards for managed values
-//! (`@` and `@mut`). This code is primarily for use by datum;
+//! Logic relating to rooting and write guards for managed values.
+//! This code is primarily for use by datum;
 //! it exists in its own module both to keep datum.rs bite-sized
 //! and for each in debugging (e.g., so you can use
 //! `RUST_LOG=rustc::middle::trans::write_guard`).
 
 
 use middle::borrowck::{RootInfo, root_map_key};
-use middle::trans::base::*;
+use middle::trans::cleanup;
 use middle::trans::common::*;
 use middle::trans::datum::*;
 use syntax::codemap::Span;
 use syntax::ast;
 
-pub fn root_and_write_guard<'a>(
-                            datum: &Datum,
-                            bcx: &'a Block<'a>,
-                            span: Span,
-                            expr_id: ast::NodeId,
-                            derefs: uint)
-                            -> &'a Block<'a> {
+pub fn root_and_write_guard<'a, K:KindOps>(datum: &Datum<K>,
+                                           bcx: &'a Block<'a>,
+                                           span: Span,
+                                           expr_id: ast::NodeId,
+                                           derefs: uint) -> &'a Block<'a> {
     let key = root_map_key { id: expr_id, derefs: derefs };
     debug!("write_guard::root_and_write_guard(key={:?})", key);
 
@@ -43,13 +41,11 @@ pub fn root_and_write_guard<'a>(
     }
 }
 
-fn root<'a>(
-        datum: &Datum,
-        bcx: &'a Block<'a>,
-        _: Span,
-        root_key: root_map_key,
-        root_info: RootInfo)
-        -> &'a Block<'a> {
+fn root<'a, K:KindOps>(datum: &Datum<K>,
+                       bcx: &'a Block<'a>,
+                       _span: Span,
+                       root_key: root_map_key,
+                       root_info: RootInfo) -> &'a Block<'a> {
     //! In some cases, borrowck will decide that an @T/@[]/@str
     //! value must be rooted for the program to be safe.  In that
     //! case, we will call this function, which will stash a copy
@@ -58,17 +54,12 @@ fn root<'a>(
     debug!("write_guard::root(root_key={:?}, root_info={:?}, datum={:?})",
            root_key, root_info, datum.to_str(bcx.ccx()));
 
-    // First, root the datum. Note that we must zero this value,
+    // Root the datum. Note that we must zero this value,
     // because sometimes we root on one path but not another.
     // See e.g. #4904.
-    let scratch = scratch_datum(bcx, datum.ty, "__write_guard", true);
-    datum.copy_to_datum(bcx, INIT, scratch);
-    let cleanup_bcx = find_bcx_for_scope(bcx, root_info.scope);
-    add_clean_temp_mem_in_scope(cleanup_bcx,
-                                root_info.scope,
-                                scratch.val,
-                                scratch.ty);
-
-    bcx
+    lvalue_scratch_datum(
+        bcx, datum.ty, "__write_guard", true,
+        cleanup::AstScope(root_info.scope), (),
+        |(), bcx, llval| datum.shallow_copy_and_take(bcx, llval)).bcx
 }
 
index e8ca4ba57283f6b643187a7b233392993050c022..538a3c89bef72362e42bcc33dc49e98f27c277e0 100644 (file)
@@ -629,7 +629,7 @@ pub enum sty {
     ty_str(vstore),
     ty_enum(DefId, substs),
     ty_box(t),
-    ty_uniq(mt),
+    ty_uniq(t),
     ty_vec(mt, vstore),
     ty_ptr(mt),
     ty_rptr(Region, mt),
@@ -1091,8 +1091,10 @@ fn sflags(substs: &substs) -> uint {
               _ => {}
           }
       }
-      &ty_box(ref tt) => flags |= get(*tt).flags,
-      &ty_uniq(ref m) | &ty_vec(ref m, _) | &ty_ptr(ref m) |
+      &ty_box(tt) | &ty_uniq(tt) => {
+        flags |= get(tt).flags
+      }
+      &ty_vec(ref m, _) | &ty_ptr(ref m) |
       &ty_unboxed_vec(ref m) => {
         flags |= get(m.ty).flags;
       }
@@ -1234,15 +1236,7 @@ pub fn mk_enum(cx: ctxt, did: ast::DefId, substs: substs) -> t {
 
 pub fn mk_box(cx: ctxt, ty: t) -> t { mk_t(cx, ty_box(ty)) }
 
-pub fn mk_imm_box(cx: ctxt, ty: t) -> t {
-    mk_box(cx, ty)
-}
-
-pub fn mk_uniq(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_uniq(tm)) }
-
-pub fn mk_imm_uniq(cx: ctxt, ty: t) -> t {
-    mk_uniq(cx, mt {ty: ty, mutbl: ast::MutImmutable})
-}
+pub fn mk_uniq(cx: ctxt, ty: t) -> t { mk_t(cx, ty_uniq(ty)) }
 
 pub fn mk_ptr(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
 
@@ -1355,9 +1349,9 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
       ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
       ty_str(_) | ty_type | ty_self(_) |
       ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {}
-      ty_box(ref ty) => maybe_walk_ty(*ty, f),
+      ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
       ty_vec(ref tm, _) | ty_unboxed_vec(ref tm) | ty_ptr(ref tm) |
-      ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
+      ty_rptr(_, ref tm) => {
         maybe_walk_ty(tm.ty, f);
       }
       ty_enum(_, ref substs) | ty_struct(_, ref substs) |
@@ -1461,11 +1455,6 @@ pub fn subst(cx: ctxt,
 
 // Type utilities
 
-pub fn type_is_voidish(tcx: ctxt, ty: t) -> bool {
-    //! "nil" and "bot" are void types in that they represent 0 bits of information
-    type_is_nil(ty) || type_is_bot(ty) || type_is_empty(tcx, ty)
-}
-
 pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
 
 pub fn type_is_bot(ty: t) -> bool {
@@ -2026,6 +2015,10 @@ fn tc_ty(cx: ctxt,
                 tc_ty(cx, typ, cache).managed_pointer()
             }
 
+            ty_uniq(typ) => {
+                tc_ty(cx, typ, cache).owned_pointer()
+            }
+
             ty_trait(_, _, store, mutbl, bounds) => {
                 object_contents(cx, store, mutbl, bounds)
             }
@@ -2039,10 +2032,6 @@ fn tc_ty(cx: ctxt,
                     borrowed_contents(r, mt.mutbl))
             }
 
-            ty_uniq(mt) => {
-                tc_mt(cx, mt, cache).owned_pointer()
-            }
-
             ty_vec(mt, vstore_uniq) => {
                 tc_mt(cx, mt, cache).owned_pointer()
             }
@@ -2318,10 +2307,9 @@ fn subtypes_require(cx: ctxt, seen: &mut ~[DefId],
             ty_unboxed_vec(_) => {
                 false
             }
-            ty_box(typ) => {
+            ty_box(typ) | ty_uniq(typ) => {
                 type_requires(cx, seen, r_ty, typ)
             }
-            ty_uniq(ref mt) |
             ty_rptr(_, ref mt) => {
                 type_requires(cx, seen, r_ty, mt.ty)
             }
@@ -2596,22 +2584,22 @@ pub fn deref(t: t, explicit: bool) -> Option<mt> {
 
 pub fn deref_sty(sty: &sty, explicit: bool) -> Option<mt> {
     match *sty {
-      ty_box(typ) => {
-        Some(mt {
-          ty: typ,
-          mutbl: ast::MutImmutable,
-        })
-      }
+        ty_box(typ) | ty_uniq(typ) => {
+            Some(mt {
+                ty: typ,
+                mutbl: ast::MutImmutable,
+            })
+        }
 
-      ty_rptr(_, mt) | ty_uniq(mt) => {
-        Some(mt)
-      }
+        ty_rptr(_, mt) => {
+            Some(mt)
+        }
 
-      ty_ptr(mt) if explicit => {
-        Some(mt)
-      }
+        ty_ptr(mt) if explicit => {
+            Some(mt)
+        }
 
-      _ => None
+        _ => None
     }
 }
 
@@ -4861,9 +4849,8 @@ fn iter<T: IterBytes>(hash: &mut SipState, t: &T) {
             ty_box(_) => {
                 hash.input([9]);
             }
-            ty_uniq(m) => {
+            ty_uniq(_) => {
                 hash.input([10]);
-                mt(&mut hash, m);
             }
             ty_vec(m, v) => {
                 hash.input([11]);
index bd1f091b9d6aab8960de413aa4a2db990cd91bac..28ba566c0a4ab5063594303b8a2a03ea3d69e8e3 100644 (file)
@@ -143,8 +143,8 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
         ty::ty_box(typ) => {
             ty::ty_box(this.fold_ty(typ))
         }
-        ty::ty_uniq(ref tm) => {
-            ty::ty_uniq(this.fold_mt(tm))
+        ty::ty_uniq(typ) => {
+            ty::ty_uniq(this.fold_ty(typ))
         }
         ty::ty_ptr(ref tm) => {
             ty::ty_ptr(this.fold_mt(tm))
index 74e4c969292507f32dd8d7ea0a2adde15f2214ed..3b787581e158d4ad1099bd603907dcec43d37585 100644 (file)
@@ -410,7 +410,7 @@ fn check_path_args(tcx: ty::ctxt,
       ast::TyUniq(ty) => {
         let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
         mk_pointer(this, rscope, &mt, ty::vstore_uniq,
-                   |tmt| ty::mk_uniq(tcx, tmt))
+                   |tmt| ty::mk_uniq(tcx, tmt.ty))
       }
       ast::TyVec(ty) => {
         tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type");
@@ -691,13 +691,11 @@ fn transform_self_ty<AC:AstConv,RS:RegionScope>(
                                  ty::mt {ty: self_info.untransformed_self_ty,
                                          mutbl: mutability}))
             }
-            ast::SelfBox(_) => {
+            ast::SelfBox => {
                 Some(ty::mk_box(this.tcx(), self_info.untransformed_self_ty))
             }
             ast::SelfUniq(_) => {
-                Some(ty::mk_uniq(this.tcx(),
-                                 ty::mt {ty: self_info.untransformed_self_ty,
-                                         mutbl: ast::MutImmutable}))
+                Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
             }
         }
     }
index 0d7a1258972c4024f4ec7146433964817b9f6974..9303bf80208a7843b8941c276c6dda5f920a94c3 100644 (file)
@@ -670,7 +670,7 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
     };
     match *structure_of(fcx, span, expected) {
         ty::ty_uniq(e_inner) if pointer_kind == Send => {
-            check_inner(e_inner.ty);
+            check_inner(e_inner);
         }
         ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed => {
             check_inner(e_inner.ty);
index 910b0dbf7d891c2ded4fc7609948f1b84f65cf9d..3c0849f04b8e79ea52aaed1d1a1ab533590eb792 100644 (file)
@@ -623,9 +623,9 @@ fn consider_reborrow(&self,
          * consuming the original pointer.
          *
          * You might think that this would be a natural byproduct of
-         * the auto-deref/auto-ref process.  This is true for `@mut T`
-         * but not for an `&mut T` receiver.  With `@mut T`, we would
-         * begin by testing for methods with a self type `@mut T`,
+         * the auto-deref/auto-ref process.  This is true for `~T`
+         * but not for an `&mut T` receiver.  With `~T`, we would
+         * begin by testing for methods with a self type `~T`,
          * then autoderef to `T`, then autoref to `&mut T`.  But with
          * an `&mut T` receiver the process begins with `&mut T`, only
          * without any autoadjustments.
@@ -1057,15 +1057,15 @@ fn construct_transformed_self_ty_for_object(
          *
          *     trait Foo {
          *         fn r_method<'a>(&'a self);
-         *         fn m_method(@mut self);
+         *         fn u_method(~self);
          *     }
          *
          * Now, assuming that `r_method` is being called, we want the
-         * result to be `&'a Foo`. Assuming that `m_method` is being
-         * called, we want the result to be `@mut Foo`. Of course,
+         * result to be `&'a Foo`. Assuming that `u_method` is being
+         * called, we want the result to be `~Foo`. Of course,
          * this transformation has already been done as part of
-         * `method_ty.transformed_self_ty`, but there the
-         * type is expressed in terms of `Self` (i.e., `&'a Self`, `@mut Self`).
+         * `method_ty.transformed_self_ty`, but there the type
+         * is expressed in terms of `Self` (i.e., `&'a Self`, `~Self`).
          * Because objects are not standalone types, we can't just substitute
          * `s/Self/Foo/`, so we must instead perform this kind of hokey
          * match below.
@@ -1081,7 +1081,7 @@ fn construct_transformed_self_ty_for_object(
             ast::SelfValue(_) => {
                 ty::mk_err() // error reported in `enforce_object_limitations()`
             }
-            ast::SelfRegion(..) | ast::SelfBox(..) | ast::SelfUniq(..) => {
+            ast::SelfRegion(..) | ast::SelfBox | ast::SelfUniq(..) => {
                 let transformed_self_ty =
                     method_ty.transformed_self_ty.clone().unwrap();
                 match ty::get(transformed_self_ty).sty {
@@ -1095,9 +1095,9 @@ fn construct_transformed_self_ty_for_object(
                                      substs, BoxTraitStore, ast::MutImmutable,
                                      ty::EmptyBuiltinBounds())
                     }
-                    ty::ty_uniq(mt) => { // must be SelfUniq
+                    ty::ty_uniq(_) => { // must be SelfUniq
                         ty::mk_trait(self.tcx(), trait_def_id,
-                                     substs, UniqTraitStore, mt.mutbl,
+                                     substs, UniqTraitStore, ast::MutImmutable,
                                      ty::EmptyBuiltinBounds())
                     }
                     _ => {
@@ -1144,7 +1144,7 @@ fn enforce_object_limitations(&self,
                      through an object");
             }
 
-            ast::SelfRegion(..) | ast::SelfBox(..) | ast::SelfUniq(..) => {}
+            ast::SelfRegion(..) | ast::SelfBox | ast::SelfUniq(..) => {}
         }
 
         if ty::type_has_self(method_fty) { // reason (a) above
@@ -1219,15 +1219,14 @@ fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
                 }
             }
 
-            SelfBox(m) => {
+            SelfBox => {
                 debug!("(is relevant?) explicit self is a box");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_box(typ) => {
                         rcvr_matches_ty(self.fcx, typ, candidate)
                     }
 
-                    ty::ty_trait(self_did, _, BoxTraitStore, self_m, _) => {
-                        mutability_matches(self_m, m) &&
+                    ty::ty_trait(self_did, _, BoxTraitStore, ast::MutImmutable, _) => {
                         rcvr_matches_object(self_did, candidate)
                     }
 
@@ -1238,8 +1237,8 @@ fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
             SelfUniq(_) => {
                 debug!("(is relevant?) explicit self is a unique pointer");
                 match ty::get(rcvr_ty).sty {
-                    ty::ty_uniq(mt) => {
-                        rcvr_matches_ty(self.fcx, mt.ty, candidate)
+                    ty::ty_uniq(typ) => {
+                        rcvr_matches_ty(self.fcx, typ, candidate)
                     }
 
                     ty::ty_trait(self_did, _, UniqTraitStore, _, _) => {
index e2cad2b8e85ffe4e9f41c8bfd46f39cd46348be7..99cdbacbd5bed155d158657c91f61823e388191c 100644 (file)
@@ -1334,7 +1334,7 @@ pub fn do_autoderef(fcx: @FnCtxt, sp: Span, t: ty::t) -> (ty::t, uint) {
 
         // Some extra checks to detect weird cycles and so forth:
         match *sty {
-            ty::ty_box(inner) => {
+            ty::ty_box(inner) | ty::ty_uniq(inner) => {
                 match ty::get(t1).sty {
                     ty::ty_infer(ty::TyVar(v1)) => {
                         ty::occurs_check(fcx.ccx.tcx, sp, v1,
@@ -1343,7 +1343,7 @@ pub fn do_autoderef(fcx: @FnCtxt, sp: Span, t: ty::t) -> (ty::t, uint) {
                     _ => ()
                 }
             }
-            ty::ty_uniq(inner) | ty::ty_rptr(_, inner) => {
+            ty::ty_rptr(_, inner) => {
                 match ty::get(t1).sty {
                     ty::ty_infer(ty::TyVar(v1)) => {
                         ty::occurs_check(fcx.ccx.tcx, sp, v1,
@@ -2697,10 +2697,8 @@ fn check_struct_enum_variant(fcx: @FnCtxt,
                   let def_id = ast_util::def_id_of_def(definition);
                   match tcx.lang_items.items[ExchangeHeapLangItem as uint] {
                       Some(item_def_id) if def_id == item_def_id => {
-                          fcx.write_ty(id, ty::mk_uniq(tcx, ty::mt {
-                              ty: fcx.expr_ty(subexpr),
-                              mutbl: ast::MutImmutable,
-                          }));
+                          fcx.write_ty(id, ty::mk_uniq(tcx,
+                                                       fcx.expr_ty(subexpr)));
                           checked = true
                       }
                       Some(_) | None => {}
@@ -2806,13 +2804,12 @@ fn check_struct_enum_variant(fcx: @FnCtxt,
       ast::ExprUnary(callee_id, unop, oprnd) => {
         let exp_inner = unpack_expected(fcx, expected, |sty| {
             match unop {
-              ast::UnBox | ast::UnUniq => match *sty {
-                ty::ty_box(ty) => Some(ty),
-                ty::ty_uniq(ref mt) => Some(mt.ty),
-                _ => None
-              },
-              ast::UnNot | ast::UnNeg => expected,
-              ast::UnDeref => None
+                ast::UnBox | ast::UnUniq => match *sty {
+                    ty::ty_box(ty) | ty::ty_uniq(ty) => Some(ty),
+                    _ => None
+                },
+                ast::UnNot | ast::UnNeg => expected,
+                ast::UnDeref => None
             }
         });
         check_expr_with_opt_hint(fcx, oprnd, exp_inner);
@@ -2824,9 +2821,7 @@ fn check_struct_enum_variant(fcx: @FnCtxt,
                     oprnd_t = ty::mk_box(tcx, oprnd_t)
                 }
                 ast::UnUniq => {
-                    oprnd_t = ty::mk_uniq(tcx,
-                                          ty::mt {ty: oprnd_t,
-                                                  mutbl: ast::MutImmutable});
+                    oprnd_t = ty::mk_uniq(tcx, oprnd_t);
                 }
                 ast::UnDeref => {
                     let sty = structure_of(fcx, expr.span, oprnd_t);
@@ -3988,8 +3983,31 @@ pub fn ast_expr_vstore_to_vstore(fcx: @FnCtxt,
         ast::ExprVstoreUniq => ty::vstore_uniq,
         ast::ExprVstoreBox => ty::vstore_box,
         ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
-            let r = fcx.infcx().next_region_var(infer::AddrOfSlice(e.span));
-            ty::vstore_slice(r)
+            match e.node {
+                ast::ExprLit(..) |
+                ast::ExprVec([], _) => {
+                    // string literals and *empty slices* live in static memory
+                    ty::vstore_slice(ty::ReStatic)
+                }
+                ast::ExprRepeat(..) |
+                ast::ExprVec(..) => {
+                    // vector literals are temporaries on the stack
+                    match fcx.tcx().region_maps.temporary_scope(e.id) {
+                        Some(scope) => {
+                            let r = ty::ReScope(scope);
+                            ty::vstore_slice(r)
+                        }
+                        None => {
+                            // this slice occurs in a static somewhere
+                            ty::vstore_slice(ty::ReStatic)
+                        }
+                    }
+                }
+                _ => {
+                    fcx.ccx.tcx.sess.span_bug(
+                        e.span, format!("vstore with unexpected contents"))
+                }
+            }
         }
     }
 }
@@ -4108,7 +4126,7 @@ fn param(ccx: @CrateCtxt, n: uint) -> ty::t {
             "uninit" => (1u, ~[], param(ccx, 0u)),
             "forget" => (1u, ~[ param(ccx, 0) ], ty::mk_nil()),
             "transmute" => (2, ~[ param(ccx, 0) ], param(ccx, 1)),
-            "move_val" | "move_val_init" => {
+            "move_val_init" => {
                 (1u,
                  ~[
                     ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
index ad0482cf4f42e2439a9d7fcd20d6aeac40ebef8d..c6e43bf968e9b764568f54593ab98f11fe30b228 100644 (file)
@@ -55,21 +55,26 @@ pub struct Rcx {
     repeating_scope: ast::NodeId,
 }
 
-fn encl_region_of_def(fcx: @FnCtxt, def: ast::Def) -> ty::Region {
+fn region_of_def(fcx: @FnCtxt, def: ast::Def) -> ty::Region {
+    /*!
+     * Returns the validity region of `def` -- that is, how long
+     * is `def` valid?
+     */
+
     let tcx = fcx.tcx();
     match def {
         DefLocal(node_id, _) | DefArg(node_id, _) |
         DefSelf(node_id, _) | DefBinding(node_id, _) => {
-            tcx.region_maps.encl_region(node_id)
+            tcx.region_maps.var_region(node_id)
         }
         DefUpvar(_, subdef, closure_id, body_id) => {
             match ty::ty_closure_sigil(fcx.node_ty(closure_id)) {
-                BorrowedSigil => encl_region_of_def(fcx, *subdef),
+                BorrowedSigil => region_of_def(fcx, *subdef),
                 ManagedSigil | OwnedSigil => ReScope(body_id)
             }
         }
         _ => {
-            tcx.sess.bug(format!("unexpected def in encl_region_of_def: {:?}",
+            tcx.sess.bug(format!("unexpected def in region_of_def: {:?}",
                               def))
         }
     }
@@ -193,7 +198,6 @@ fn visit_item(_rcx: &mut Rcx, _item: &ast::Item) {
 }
 
 fn visit_block(rcx: &mut Rcx, b: &ast::Block) {
-    rcx.fcx.tcx().region_maps.record_cleanup_scope(b.id);
     visit::walk_block(rcx, b, ());
 }
 
@@ -209,6 +213,7 @@ fn visit_arm(rcx: &mut Rcx, arm: &ast::Arm) {
 fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
     // see above
     constrain_bindings_in_pat(l.pat, rcx);
+    guarantor::for_local(rcx, l);
     visit::walk_local(rcx, l, ());
 }
 
@@ -239,9 +244,9 @@ fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
         // that the lifetime of any regions that appear in a
         // variable's type enclose at least the variable's scope.
 
-        let encl_region = tcx.region_maps.encl_region(id);
+        let var_region = tcx.region_maps.var_region(id);
         constrain_regions_in_type_of_node(
-            rcx, id, encl_region,
+            rcx, id, var_region,
             infer::BindingTypeIsNotValidAtDecl(span));
     })
 }
@@ -255,55 +260,6 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
         method_map.get().contains_key(&expr.id)
     };
 
-    // Record cleanup scopes, which are used by borrowck to decide the
-    // maximum lifetime of a temporary rvalue.  These were derived by
-    // examining where trans creates block scopes, not because this
-    // reflects some principled decision around temporary lifetimes.
-    // Ordinarily this would seem like something that should be setup
-    // in region, but we need to know which uses of operators are
-    // overloaded.  See #3511.
-    let tcx = rcx.fcx.tcx();
-    match expr.node {
-        // You'd think that x += y where `+=` is overloaded would be a
-        // cleanup scope. You'd be... kind of right. In fact the
-        // handling of `+=` and friends in trans for overloaded
-        // operators is a hopeless mess and I can't figure out how to
-        // represent it. - ndm
-        //
-        // ast::expr_assign_op(..) |
-
-        ast::ExprIndex(..) |
-        ast::ExprBinary(..) |
-        ast::ExprUnary(..) if has_method_map => {
-            tcx.region_maps.record_cleanup_scope(expr.id);
-        }
-        ast::ExprBinary(_, ast::BiAnd, lhs, rhs) |
-        ast::ExprBinary(_, ast::BiOr, lhs, rhs) => {
-            tcx.region_maps.record_cleanup_scope(lhs.id);
-            tcx.region_maps.record_cleanup_scope(rhs.id);
-        }
-        ast::ExprCall(..) |
-        ast::ExprMethodCall(..) => {
-            tcx.region_maps.record_cleanup_scope(expr.id);
-        }
-        ast::ExprMatch(_, ref arms) => {
-            tcx.region_maps.record_cleanup_scope(expr.id);
-            for arm in arms.iter() {
-                for guard in arm.guard.iter() {
-                    tcx.region_maps.record_cleanup_scope(guard.id);
-                }
-            }
-        }
-        ast::ExprLoop(ref body, _) => {
-            tcx.region_maps.record_cleanup_scope(body.id);
-        }
-        ast::ExprWhile(cond, ref body) => {
-            tcx.region_maps.record_cleanup_scope(cond.id);
-            tcx.region_maps.record_cleanup_scope(body.id);
-        }
-        _ => {}
-    }
-
     // Check any autoderefs or autorefs that appear.
     {
         let adjustments = rcx.fcx.inh.adjustments.borrow();
@@ -701,10 +657,10 @@ fn constrain_free_variables(rcx: &mut Rcx,
     for freevar in get_freevars(tcx, expr.id).iter() {
         debug!("freevar def is {:?}", freevar.def);
         let def = freevar.def;
-        let en_region = encl_region_of_def(rcx.fcx, def);
-        debug!("en_region = {}", en_region.repr(tcx));
+        let def_region = region_of_def(rcx.fcx, def);
+        debug!("def_region = {}", def_region.repr(tcx));
         rcx.fcx.mk_subr(true, infer::FreeVariable(freevar.span),
-                        region, en_region);
+                        region, def_region);
     }
 }
 
@@ -873,6 +829,30 @@ pub fn for_match(rcx: &mut Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
         }
     }
 
+    pub fn for_local(rcx: &mut Rcx, local: &ast::Local) {
+        /*!
+         * Link the lifetimes of any ref bindings in a let
+         * pattern to the lifetimes in the initializer.
+         *
+         * For example, given something like this:
+         *
+         *    let &Foo(ref x) = ...;
+         *
+         * this would ensure that the lifetime 'a of the
+         * region pointer being matched must be >= the lifetime
+         * of the ref binding.
+         */
+
+        debug!("regionck::for_match()");
+        let init_expr = match local.init {
+            None => { return; }
+            Some(e) => e
+        };
+        let init_guarantor = guarantor(rcx, init_expr);
+        debug!("init_guarantor={}", init_guarantor.repr(rcx.tcx()));
+        link_ref_bindings_in_pat(rcx, local.pat, init_guarantor);
+    }
+
     pub fn for_autoref(rcx: &mut Rcx,
                        expr: &ast::Expr,
                        autoderefs: uint,
index 9b9a211ea71ae9ba5f999b7b0bac230950c3816e..5dbcae7418bc6f2296e0358d5e75a4cc4f32a23a 100644 (file)
@@ -582,14 +582,14 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
               let ty = structurally_resolved_type(fcx, ex.span,
                                                   fcx.expr_ty(src));
               match (&ty::get(ty).sty, store) {
-                  (&ty::ty_box(..), ty::BoxTraitStore)
+                  (&ty::ty_box(..), ty::BoxTraitStore) |
+                  (&ty::ty_uniq(..), ty::UniqTraitStore)
                     if !mutability_allowed(ast::MutImmutable,
                                            target_mutbl) => {
                       fcx.tcx().sess.span_err(ex.span,
                                               format!("types differ in mutability"));
                   }
 
-                  (&ty::ty_uniq(mt), ty::UniqTraitStore) |
                   (&ty::ty_rptr(_, mt), ty::RegionTraitStore(..))
                     if !mutability_allowed(mt.mutbl, target_mutbl) => {
                       fcx.tcx().sess.span_err(ex.span,
@@ -600,8 +600,8 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
                   (&ty::ty_uniq(..), ty::UniqTraitStore) |
                   (&ty::ty_rptr(..), ty::RegionTraitStore(..)) => {
                     let typ = match (&ty::get(ty).sty) {
-                        &ty::ty_box(typ) => typ,
-                        &ty::ty_uniq(mt) | &ty::ty_rptr(_, mt) => mt.ty,
+                        &ty::ty_box(typ) | &ty::ty_uniq(typ) => typ,
+                        &ty::ty_rptr(_, mt) => mt.ty,
                         _ => fail!("shouldn't get here"),
                     };
 
index eaf6cea244b90e372e3a45547ea2e520d14c2b5f..f9193c4f73c2a2bed937da44a2f4947945489d19 100644 (file)
@@ -560,7 +560,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
     debug!("convert: item {} with id {}", tcx.sess.str_of(it.ident), it.id);
     match it.node {
       // These don't define types.
-      ast::ItemForeignMod(_) | ast::ItemMod(_) => {}
+      ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
       ast::ItemEnum(ref enum_definition, ref generics) => {
           ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
           let tpt = ty_of_item(ccx, it);
@@ -913,8 +913,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
             return tpt;
         }
         ast::ItemImpl(..) | ast::ItemMod(_) |
-        ast::ItemForeignMod(_) => fail!(),
-        ast::ItemMac(..) => fail!("item macros unimplemented")
+        ast::ItemForeignMod(_) | ast::ItemMac(_) => fail!(),
     }
 }
 
index 6c4a82c628afd1ae4338852e415a3db8a1372803..5008dd8a0dbc57c609371e93415f71eee7f21112 100644 (file)
@@ -245,8 +245,7 @@ pub fn coerce_borrowed_pointer(&self,
         let r_borrow = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
 
         let inner_ty = match *sty_a {
-            ty::ty_box(typ) => typ,
-            ty::ty_uniq(mt_a) => mt_a.ty,
+            ty::ty_box(typ) | ty::ty_uniq(typ) => typ,
             ty::ty_rptr(_, mt_a) => mt_a.ty,
             _ => {
                 return self.subtype(a, b);
index 01e19f011aa61354119f3be320e37af6220a3804..e5d9ee97098140f6b31b1aae34bb234c04c725c8 100644 (file)
@@ -521,8 +521,8 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
         this.tys(a_inner, b_inner).and_then(|typ| Ok(ty::mk_box(tcx, typ)))
       }
 
-      (&ty::ty_uniq(ref a_mt), &ty::ty_uniq(ref b_mt)) => {
-        this.mts(a_mt, b_mt).and_then(|mt| Ok(ty::mk_uniq(tcx, mt)))
+      (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
+        this.tys(a_inner, b_inner).and_then(|typ| Ok(ty::mk_uniq(tcx, typ)))
       }
 
       (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
index 509836512c09dcfe8ebc905432f098ff3c6980ff..1db05f16875865ab5b21dfef00e72814bb1826b6 100644 (file)
@@ -634,11 +634,10 @@ fn add_constraints_from_ty(&mut self,
                 self.add_constraints_from_mt(mt, variance);
             }
 
-            ty::ty_box(typ) => {
+            ty::ty_uniq(typ) | ty::ty_box(typ) => {
                 self.add_constraints_from_ty(typ, variance);
             }
 
-            ty::ty_uniq(ref mt) |
             ty::ty_ptr(ref mt) => {
                 self.add_constraints_from_mt(mt, variance);
             }
index 84dece87750a030629a5d2f7710779c735f78119..b9916749fe9a12c960414a68973ede573bd1d019 100644 (file)
@@ -455,7 +455,7 @@ fn push_sig_to_str(cx: ctxt,
       ty_uint(t) => ast_util::uint_ty_to_str(t),
       ty_float(t) => ast_util::float_ty_to_str(t),
       ty_box(typ) => ~"@" + ty_to_str(cx, typ),
-      ty_uniq(ref tm) => ~"~" + mt_to_str(cx, tm),
+      ty_uniq(typ) => ~"~" + ty_to_str(cx, typ),
       ty_ptr(ref tm) => ~"*" + mt_to_str(cx, tm),
       ty_rptr(r, ref tm) => {
         region_ptr_to_str(cx, r) + mt_to_str(cx, tm)
@@ -673,6 +673,14 @@ fn repr(&self, tcx: ctxt) -> ~str {
     }
 }
 
+impl Repr for ast::Stmt {
+    fn repr(&self, tcx: ctxt) -> ~str {
+        format!("stmt({}: {})",
+                ast_util::stmt_id(self),
+                pprust::stmt_to_str(self, tcx.sess.intr()))
+    }
+}
+
 impl Repr for ast::Pat {
     fn repr(&self, tcx: ctxt) -> ~str {
         format!("pat({}: {})",
index 73d39d8145fc54070b61b5fa7ee1e4dd53b195af..ee2f7638be988734fa9f26ee967d0bdf139eb5aa 100644 (file)
@@ -523,6 +523,7 @@ fn output_bits(&self) -> uint { 256 }
 #[cfg(test)]
 mod tests {
     use super::{Digest, Sha256, FixedBuffer};
+    use std::num::Bounded;
     use std::vec;
     use std::rand::isaac::IsaacRng;
     use std::rand::Rng;
index 2b03ece5d5aff726ee7015598e5d3b156aea3ec2..e48c0800506f90bd9cf359efb03efb1dfdc4d290 100644 (file)
@@ -377,7 +377,7 @@ pub enum SelfTy {
     SelfStatic,
     SelfValue,
     SelfBorrowed(Option<Lifetime>, Mutability),
-    SelfManaged(Mutability),
+    SelfManaged,
     SelfOwned,
 }
 
@@ -388,7 +388,7 @@ fn clean(&self) -> SelfTy {
             ast::SelfValue(_) => SelfValue,
             ast::SelfUniq(_) => SelfOwned,
             ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
-            ast::SelfBox(mt) => SelfManaged(mt.clean()),
+            ast::SelfBox => SelfManaged,
         }
     }
 }
index 947038bc8d85fc1d7d816a2362514441c29fc0d9..8501a01d34bcf140073fddf7cf357497801b6942 100644 (file)
@@ -10,6 +10,7 @@
 
 use rustc;
 use rustc::{driver, middle};
+use rustc::metadata::creader::Loader;
 use rustc::middle::privacy;
 
 use syntax::ast;
@@ -41,15 +42,15 @@ pub struct CrateAnalysis {
 fn get_ast_and_resolve(cpath: &Path,
                        libs: HashSet<Path>, cfgs: ~[~str]) -> (DocContext, CrateAnalysis) {
     use syntax::codemap::dummy_spanned;
-    use rustc::driver::driver::{file_input, build_configuration,
+    use rustc::driver::driver::{FileInput, build_configuration,
                                 phase_1_parse_input,
                                 phase_2_configure_and_expand,
                                 phase_3_run_analysis_passes};
 
     let parsesess = parse::new_parse_sess(None);
-    let input = file_input(cpath.clone());
+    let input = FileInput(cpath.clone());
 
-    let sessopts = @driver::session::options {
+    let sessopts = @driver::session::Options {
         binary: ~"rustdoc",
         maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
         addl_lib_search_paths: @RefCell::new(libs),
@@ -74,7 +75,8 @@ fn get_ast_and_resolve(cpath: &Path,
     }
 
     let crate = phase_1_parse_input(sess, cfg.clone(), &input);
-    let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, crate);
+    let loader = &mut Loader::new(sess);
+    let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, loader, crate);
     let driver::driver::CrateAnalysis {
         exported_items, public_items, ty_cx, ..
     } = phase_3_run_analysis_passes(sess, &crate, ast_map);
index 0838085b9cbeee57633104ea82ddd84f54f2bd1a..e84b5bafaa83e52027e283f2decde54db2cba272 100644 (file)
@@ -405,8 +405,7 @@ fn fmt(m: &Method<'a>, f: &mut fmt::Formatter) {
             clean::SelfStatic => {},
             clean::SelfValue => args.push_str("self"),
             clean::SelfOwned => args.push_str("~self"),
-            clean::SelfManaged(clean::Mutable) => args.push_str("@mut self"),
-            clean::SelfManaged(clean::Immutable) => args.push_str("@self"),
+            clean::SelfManaged => args.push_str("@self"),
             clean::SelfBorrowed(Some(ref lt), clean::Immutable) => {
                 args.push_str(format!("&amp;{} self", *lt));
             }
index 007a4502a1a66099e5cdbdc770c1fcd3bf6e5354..64328cdd7c3c6313b554165ac49684ceda09296b 100644 (file)
@@ -274,7 +274,8 @@ pub fn run(mut crate: clean::Crate, dst: Path) {
         write!(w, "var allPaths = \\{");
         for (i, (&id, &(ref fqp, short))) in cache.paths.iter().enumerate() {
             if i > 0 { write!(w, ","); }
-            write!(w, "'{}':\\{type:'{}',name:'{}'\\}", id, short, *fqp.last());
+            write!(w, "'{}':\\{type:'{}',name:'{}'\\}",
+                   id, short, *fqp.last());
         }
         write!(w, "\\};");
         w.flush();
index faa22672736ce29e12ab887dbeb6c1c8b8c8879d..b2500a1bc68a26acc20dc1e3a296840cff1b0add 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -11,7 +11,7 @@
 /*jslint browser: true, es5: true */
 /*globals $: true, searchIndex: true, rootPath: true, allPaths: true */
 
-(function () {
+(function() {
     "use strict";
     var resizeTimeout, interval;
 
@@ -21,9 +21,9 @@
         if (resizeTimeout) {
             clearTimeout(resizeTimeout);
         }
-        resizeTimeout = setTimeout(function () {
+        resizeTimeout = setTimeout(function() {
             var contentWidth = $('.content').width();
-            $('.docblock.short').width(function () {
+            $('.docblock.short').width(function() {
                 return contentWidth - 40 - $(this).prev().width();
             }).addClass('nowrap');
         }, 150);
@@ -50,7 +50,7 @@
     highlightSourceLines();
     $(window).on('hashchange', highlightSourceLines);
 
-    $(document).on('keyup', function (e) {
+    $(document).on('keyup', function(e) {
         if (document.activeElement.tagName === 'INPUT') {
             return;
         }
             e.preventDefault();
             $('.search-input').focus();
         }
-    }).on('click', function (e) {
+    }).on('click', function(e) {
         if (!$(e.target).closest('#help').length) {
             $('#help').addClass('hidden');
         }
     });
 
-    $('.version-selector').on('change', function () {
+    $('.version-selector').on('change', function() {
         var i, match,
             url = document.location.href,
             stripped = '',
         // clear cached values from the search bar
         $(".search-input")[0].value = '';
 
+        /**
+         * Executes the query and builds an index of results
+         * @param  {[Object]} query     [The user query]
+         * @param  {[type]} max         [The maximum results returned]
+         * @param  {[type]} searchWords [The list of search words to query against]
+         * @return {[type]}             [A search index of results]
+         */
         function execQuery(query, max, searchWords) {
             var valLower = query.query.toLowerCase(),
                 val = valLower,
                 typeFilter = query.type,
                 results = [],
                 aa = 0,
-                bb = 0;
+                bb = 0,
+                split = valLower.split("::");
+
+            //remove empty keywords
+            for (var j = 0; j < split.length; j++) {
+                split[j].toLowerCase();
+                if (split[j] === "") {
+                    split.splice(j, 1);
+                }
+            }
 
             // quoted values mean literal search
             bb = searchWords.length;
             } else {
                 // gather matching search results up to a certain maximum
                 val = val.replace(/\_/g, "");
-                for (aa = 0; aa < bb; aa += 1) {
-                    if (searchWords[aa].indexOf(val) > -1 || searchWords[aa].replace(/_/g, "").indexOf(val) > -1) {
-                        // filter type: ... queries
-                        if (!typeFilter || typeFilter === searchIndex[aa].ty) {
-                            results.push([aa, searchWords[aa].replace(/_/g, "").indexOf(val)]);
+                for (var i = 0; i < split.length; i++) {
+                    for (aa = 0; aa < bb; aa += 1) {
+                        if (searchWords[aa].indexOf(split[i]) > -1 || searchWords[aa].indexOf(val) > -1 || searchWords[aa].replace(/_/g, "").indexOf(val) > -1) {
+                            // filter type: ... queries
+                            if (!typeFilter || typeFilter === searchIndex[aa].ty) {
+                                results.push([aa, searchWords[aa].replace(/_/g, "").indexOf(val)]);
+                            }
+                        }
+                        if (results.length === max) {
+                            break;
                         }
-                    }
-                    if (results.length === max) {
-                        break;
                     }
                 }
             }
+
             bb = results.length;
             for (aa = 0; aa < bb; aa += 1) {
                 results[aa].push(searchIndex[results[aa][0]].ty);
-            }
-            for (aa = 0; aa < bb; aa += 1) {
                 results[aa].push(searchIndex[results[aa][0]].path);
+                results[aa].push(searchIndex[results[aa][0]].name);
+                results[aa].push(searchIndex[results[aa][0]].parent);
             }
-
             // if there are no results then return to default and fail
             if (results.length === 0) {
                 return [];
                     results[aa][0] = -1;
                 }
             }
-
+            for (var i = 0; i < results.length; i++) {
+                var result = results[i],
+                    name = result[4].toLowerCase(),
+                    path = result[3].toLowerCase(),
+                    parent = allPaths[result[5]];
+
+                var valid = validateResult(name, path, split, parent);
+                if (!valid) {
+                    result[0] = -1;
+                }
+            }
             return results;
         }
 
+        /**
+         * Validate performs the following boolean logic. For example: "File::open" will give
+         * IF A PARENT EXISTS => ("file" && "open") exists in (name || path || parent)
+         * OR => ("file" && "open") exists in (name || path )
+         *
+         * This could be written functionally, but I wanted to minimise functions on stack.
+         * @param  {[string]} name   [The name of the result]
+         * @param  {[string]} path   [The path of the result]
+         * @param  {[string]} keys   [The keys to be used (["file", "open"])]
+         * @param  {[object]} parent [The parent of the result]
+         * @return {[boolean]}       [Whether the result is valid or not]
+         */
+        function validateResult(name, path, keys, parent) {
+            //initially valid
+            var validate = true;
+            //if there is a parent, then validate against parent
+            if (parent !== undefined) {
+                for (var i = 0; i < keys.length; i++) {
+                    // if previous keys are valid and current key is in the path, name or parent
+                    if ((validate) && (name.toLowerCase().indexOf(keys[i]) > -1 || path.toLowerCase().indexOf(keys[i]) > -1 || parent.name.toLowerCase().indexOf(keys[i]) > -1)) {
+                        validate = true;
+                    } else {
+                        validate = false;
+                    }
+                }
+            } else {
+                for (var i = 0; i < keys.length; i++) {
+                    // if previous keys are valid and current key is in the path, name
+                    if ((validate) && (name.toLowerCase().indexOf(keys[i]) > -1 || path.toLowerCase().indexOf(keys[i]) > -1)) {
+                        validate = true;
+                    } else {
+                        validate = false;
+                    }
+                }
+            }
+            return validate;
+        }
+
         function getQuery() {
             var matches, type, query = $('.search-input').val();
 
         function initSearchNav() {
             var hoverTimeout, $results = $('.search-results .result');
 
-            $results.on('click', function () {
+            $results.on('click', function() {
                 var dst = $(this).find('a')[0];
                 console.log(window.location.pathname, dst.pathname);
                 if (window.location.pathname == dst.pathname) {
                     $('#main').removeClass('hidden');
                 }
                 document.location.href = dst.href;
-            }).on('mouseover', function () {
+            }).on('mouseover', function() {
                 var $el = $(this);
                 clearTimeout(hoverTimeout);
-                hoverTimeout = setTimeout(function () {
+                hoverTimeout = setTimeout(function() {
                     $results.removeClass('highlighted');
                     $el.addClass('highlighted');
                 }, 20);
             });
 
             $(document).off('keypress.searchnav');
-            $(document).on('keypress.searchnav', function (e) {
+            $(document).on('keypress.searchnav', function(e) {
                 var $active = $results.filter('.highlighted');
 
                 if (e.keyCode === 38) { // up
             if (results.length > 0) {
                 shown = [];
 
-                results.forEach(function (item) {
+                results.forEach(function(item) {
                     var name, type;
 
                     if (shown.indexOf(item) !== -1) {
                     if (type === 'mod') {
                         output += item.path +
                             '::<a href="' + rootPath +
-                                            item.path.replace(/::/g, '/') + '/' +
-                                            name + '/index.html" class="' +
-                                            type + '">' + name + '</a>';
+                            item.path.replace(/::/g, '/') + '/' +
+                            name + '/index.html" class="' +
+                            type + '">' + name + '</a>';
                     } else if (type === 'static' || type === 'reexport') {
                         output += item.path +
                             '::<a href="' + rootPath +
-                                            item.path.replace(/::/g, '/') +
-                                            '/index.html" class="' + type +
-                                            '">' + name + '</a>';
+                            item.path.replace(/::/g, '/') +
+                            '/index.html" class="' + type +
+                            '">' + name + '</a>';
                     } else if (item.parent !== undefined) {
                         var myparent = allPaths[item.parent];
                         var anchor = '#' + type + '.' + name;
                         output += item.path + '::' + myparent.name +
                             '::<a href="' + rootPath +
-                                            item.path.replace(/::/g, '/') +
-                                            '/' + myparent.type +
-                                            '.' + myparent.name +
-                                            '.html' + anchor +
-                                            '" class="' + type +
-                                            '">' + name + '</a>';
+                            item.path.replace(/::/g, '/') +
+                            '/' + myparent.type +
+                            '.' + myparent.name +
+                            '.html' + anchor +
+                            '" class="' + type +
+                            '">' + name + '</a>';
                     } else {
                         output += item.path +
                             '::<a href="' + rootPath +
-                                            item.path.replace(/::/g, '/') +
-                                            '/' + type +
-                                            '.' + name +
-                                            '.html" class="' + type +
-                                            '">' + name + '</a>';
+                            item.path.replace(/::/g, '/') +
+                            '/' + type +
+                            '.' + name +
+                            '.html" class="' + type +
+                            '">' + name + '</a>';
                     }
 
                     output += '</td><td><span class="desc">' + item.desc +
-                                    '</span></td></tr>';
+                        '</span></td></tr>';
                 });
             } else {
                 output += 'No results :( <a href="https://duckduckgo.com/?q=' +
-                            encodeURIComponent('rust ' + query.query) +
-                            '">Try on DuckDuckGo?</a>';
+                    encodeURIComponent('rust ' + query.query) +
+                    '">Try on DuckDuckGo?</a>';
             }
 
             output += "</p>";
             $('#main.content').addClass('hidden');
             $('#search.content').removeClass('hidden').html(output);
             $('#search .desc').width($('#search').width() - 40 -
-                    $('#search td:first-child').first().width());
+                $('#search td:first-child').first().width());
             initSearchNav();
         }
 
         function search(e) {
-            var query, filterdata = [], obj, i, len,
+            var query,
+                filterdata = [],
+                obj, i, len,
                 results = [],
                 maxResults = 200,
                 resultIndex;
         function startSearch() {
             var keyUpTimeout;
             $('.do-search').on('click', search);
-            $('.search-input').on('keyup', function () {
+            $('.search-input').on('keyup', function() {
                 clearTimeout(keyUpTimeout);
                 keyUpTimeout = setTimeout(search, 100);
             });
index 31a500718eed9662a55af42d6878b77bfce1c606..53a1e5697ef340cb403dd1833ccf145cb3c6b802 100644 (file)
@@ -20,6 +20,7 @@
 use extra::test;
 use rustc::driver::driver;
 use rustc::driver::session;
+use rustc::metadata::creader::Loader;
 use syntax::diagnostic;
 use syntax::parse;
 
 
 pub fn run(input: &str, matches: &getopts::Matches) -> int {
     let parsesess = parse::new_parse_sess(None);
-    let input = driver::file_input(Path::new(input));
+    let input = driver::FileInput(Path::new(input));
     let libs = matches.opt_strs("L").map(|s| Path::new(s.as_slice()));
     let libs = @RefCell::new(libs.move_iter().collect());
 
-    let sessopts = @session::options {
+    let sessopts = @session::Options {
         binary: ~"rustdoc",
         maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
         addl_lib_search_paths: libs,
@@ -58,7 +59,8 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int {
 
     let cfg = driver::build_configuration(sess);
     let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
-    let (crate, _) = driver::phase_2_configure_and_expand(sess, cfg, crate);
+    let loader = &mut Loader::new(sess);
+    let (crate, _) = driver::phase_2_configure_and_expand(sess, cfg, loader, crate);
 
     let ctx = @core::DocContext {
         crate: crate,
@@ -95,9 +97,9 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int {
 fn runtest(test: &str, cratename: &str, libs: HashSet<Path>) {
     let test = maketest(test, cratename);
     let parsesess = parse::new_parse_sess(None);
-    let input = driver::str_input(test);
+    let input = driver::StrInput(test);
 
-    let sessopts = @session::options {
+    let sessopts = @session::Options {
         binary: ~"rustdoctest",
         maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
         addl_lib_search_paths: @RefCell::new(libs),
index 5f86fa0e213e4f3729e65795787d14a74dfde3ee..ac94c477e7836bfe2b4e578423f1d6af5a98b873 100644 (file)
@@ -28,6 +28,7 @@
 
 use extra::workcache;
 use rustc::driver::{driver, session};
+use rustc::metadata::creader::Loader;
 use rustc::metadata::filesearch;
 use rustc::metadata::filesearch::rust_path;
 use rustc::util::sha2;
@@ -106,19 +107,23 @@ fn parse<'a>(sysroot: Path,
         // Build the rustc session data structures to pass
         // to the compiler
         debug!("pkgscript parse: {}", sysroot.display());
-        let options = @session::options {
+        let options = @session::Options {
             binary: binary,
             maybe_sysroot: Some(@sysroot),
             outputs: ~[session::OutputExecutable],
             .. (*session::basic_options()).clone()
         };
-        let input = driver::file_input(script.clone());
+        let input = driver::FileInput(script.clone());
         let sess = driver::build_session(options,
                                          @diagnostic::DefaultEmitter as
                                             @diagnostic::Emitter);
         let cfg = driver::build_configuration(sess);
         let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
-        let crate_and_map = driver::phase_2_configure_and_expand(sess, cfg.clone(), crate);
+        let loader = &mut Loader::new(sess);
+        let crate_and_map = driver::phase_2_configure_and_expand(sess,
+                                                         cfg.clone(),
+                                                         loader,
+                                                         crate);
         let work_dir = build_pkg_id_in_workspace(id, workspace);
 
         debug!("Returning package script with id {}", id.to_str());
@@ -141,7 +146,7 @@ fn build_custom(&mut self, exec: &mut workcache::Exec) -> ~str {
         let (crate, ast_map) = self.crate_and_map.take_unwrap();
         let crate = util::ready_crate(sess, crate);
         debug!("Building output filenames with script name {}",
-               driver::source_name(&driver::file_input(self.input.clone())));
+               driver::source_name(&driver::FileInput(self.input.clone())));
         let exe = self.build_dir.join("pkg" + util::exe_suffix());
         util::compile_crate_from_input(&self.input,
                                        exec,
index 06970561fac4f1652f3198c86ed16fa20dfedd51..909b25fe7563b2151e49f4bc974ac46c39181c6c 100644 (file)
@@ -445,6 +445,7 @@ fn output_bits(&self) -> uint { 160 }
 
 #[cfg(test)]
 mod tests {
+    use std::num::Bounded;
     use std::rand::{IsaacRng, Rng};
     use std::vec;
     use extra::hex::FromHex;
index 99f1d9d67bc7b77c6e64ec8bc0bf5c4af980eb96..4d8f5c668b74fd5645a12a7020859dd6cb06b205 100644 (file)
 use std::io;
 use std::io::fs;
 use extra::workcache;
+use rustc::metadata::creader::Loader;
 use rustc::driver::{driver, session};
 use extra::getopts::groups::getopts;
 use syntax;
 use syntax::codemap::{DUMMY_SP, Spanned};
-use syntax::ext::base::ExtCtxt;
+use syntax::ext::base;
+use syntax::ext::base::{ExtCtxt, MacroCrate};
 use syntax::{ast, attr, codemap, diagnostic, fold, visit};
 use syntax::attr::AttrMetaMethods;
 use syntax::fold::Folder;
@@ -63,9 +65,9 @@ struct ListenerFn {
     path: ~[ast::Ident]
 }
 
-struct ReadyCtx {
+struct ReadyCtx<'a> {
     sess: session::Session,
-    ext_cx: ExtCtxt,
+    ext_cx: ExtCtxt<'a>,
     path: ~[ast::Ident],
     fns: ~[ListenerFn]
 }
@@ -130,7 +132,7 @@ fn fold_item(item: @ast::Item, fold: &mut CrateSetup)
 }
 
 struct CrateSetup<'a> {
-    ctx: &'a mut ReadyCtx,
+    ctx: &'a mut ReadyCtx<'a>,
 }
 
 impl<'a> fold::Folder for CrateSetup<'a> {
@@ -145,9 +147,10 @@ fn fold_mod(&mut self, module: &ast::Mod) -> ast::Mod {
 /// Generate/filter main function, add the list of commands, etc.
 pub fn ready_crate(sess: session::Session,
                    crate: ast::Crate) -> ast::Crate {
+    let loader = &mut Loader::new(sess);
     let mut ctx = ReadyCtx {
         sess: sess,
-        ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
+        ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(), loader),
         path: ~[],
         fns: ~[]
     };
@@ -168,7 +171,7 @@ pub fn compile_input(context: &BuildContext,
                      opt: session::OptLevel,
                      what: OutputType) -> Option<Path> {
     assert!(in_file.components().nth(1).is_some());
-    let input = driver::file_input(in_file.clone());
+    let input = driver::FileInput(in_file.clone());
     debug!("compile_input: {} / {:?}", in_file.display(), what);
     // tjc: by default, use the package ID name as the link name
     // not sure if we should support anything else
@@ -225,7 +228,7 @@ pub fn compile_input(context: &BuildContext,
 
     debug!("Output type = {:?}", output_type);
 
-    let options = @session::options {
+    let options = @session::Options {
         optimize: opt,
         test: what == Test || what == Bench,
         maybe_sysroot: Some(sysroot_to_use),
@@ -269,23 +272,41 @@ pub fn compile_input(context: &BuildContext,
     // `extern mod` directives.
     let cfg = driver::build_configuration(sess);
     let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
-    let (mut crate, ast_map) = driver::phase_2_configure_and_expand(sess, cfg.clone(), crate);
-
-    debug!("About to call find_and_install_dependencies...");
-
-    find_and_install_dependencies(context, pkg_id, in_file, sess, exec, &crate, deps,
-                                  |p| {
-                                      debug!("a dependency: {}", p.display());
-                                      let mut addl_lib_search_paths =
-                                        addl_lib_search_paths.borrow_mut();
-                                      let addl_lib_search_paths =
-                                        addl_lib_search_paths.get();
-                                      let mut addl_lib_search_paths =
-                                        addl_lib_search_paths.borrow_mut();
-                                      // Pass the directory containing a dependency
-                                      // as an additional lib search path
-                                      addl_lib_search_paths.get().insert(p);
-                                  });
+
+    let (mut crate, ast_map) = {
+        let installer = CrateInstaller {
+            context: context,
+            parent: pkg_id,
+            parent_crate: in_file,
+            sess: sess,
+            exec: exec,
+            deps: deps,
+            save: |p| {
+                debug!("a dependency: {}", p.display());
+                let mut addl_lib_search_paths =
+                    addl_lib_search_paths.borrow_mut();
+                let addl_lib_search_paths =
+                    addl_lib_search_paths.get();
+                let mut addl_lib_search_paths =
+                    addl_lib_search_paths.borrow_mut();
+                // Pass the directory containing a dependency
+                // as an additional lib search path
+                addl_lib_search_paths.get().insert(p);
+            },
+        };
+        let mut loader = CrateLoader {
+            installer: installer,
+            loader: Loader::new(sess),
+        };
+        let (crate, ast_map) = driver::phase_2_configure_and_expand(sess,
+                                                     cfg.clone(),
+                                                     &mut loader,
+                                                     crate);
+        let CrateLoader { mut installer, .. } = loader;
+        debug!("About to call find_and_install_dependencies...");
+        find_and_install_dependencies(&mut installer, &crate);
+        (crate, ast_map)
+    };
 
     // Inject the crate_id attribute so we get the right package name and version
     if !attr::contains_name(crate.attrs, "crate_id") {
@@ -352,7 +373,7 @@ pub fn compile_crate_from_input(input: &Path,
 
     // bad copy
     debug!("out_dir = {}", out_dir.display());
-    let file_input = driver::file_input(input.clone());
+    let file_input = driver::FileInput(input.clone());
     let mut outputs = driver::build_output_filenames(&file_input,
                                                      &Some(out_dir.clone()), &None,
                                                      crate.attrs, sess);
@@ -430,19 +451,18 @@ pub fn compile_crate(ctxt: &BuildContext,
     compile_input(ctxt, exec, pkg_id, crate, workspace, deps, flags, cfgs, opt, what)
 }
 
-struct ViewItemVisitor<'a> {
+struct CrateInstaller<'a> {
     context: &'a BuildContext,
     parent: &'a CrateId,
     parent_crate: &'a Path,
     sess: session::Session,
     exec: &'a mut workcache::Exec,
-    c: &'a ast::Crate,
     save: 'a |Path|,
     deps: &'a mut DepMap
 }
 
-impl<'a> Visitor<()> for ViewItemVisitor<'a> {
-    fn visit_view_item(&mut self, vi: &ast::ViewItem, env: ()) {
+impl<'a> CrateInstaller<'a> {
+    fn install_crate(&mut self, vi: &ast::ViewItem) {
         use conditions::nonexistent_package::cond;
 
         match vi.node {
@@ -585,33 +605,43 @@ fn visit_view_item(&mut self, vi: &ast::ViewItem, env: ()) {
             // Ignore `use`s
             _ => ()
         }
+    }
+}
+
+impl<'a> Visitor<()> for CrateInstaller<'a> {
+    fn visit_view_item(&mut self, vi: &ast::ViewItem, env: ()) {
+        self.install_crate(vi);
         visit::walk_view_item(self, vi, env)
     }
 }
 
+struct CrateLoader<'a> {
+    installer: CrateInstaller<'a>,
+    loader: Loader,
+}
+
+impl<'a> base::CrateLoader for CrateLoader<'a> {
+    fn load_crate(&mut self, crate: &ast::ViewItem) -> MacroCrate {
+        self.installer.install_crate(crate);
+        self.loader.load_crate(crate)
+    }
+
+    fn get_exported_macros(&mut self, cnum: ast::CrateNum) -> ~[@ast::Item] {
+        self.loader.get_exported_macros(cnum)
+    }
+
+    fn get_registrar_symbol(&mut self, cnum: ast::CrateNum) -> Option<~str> {
+        self.loader.get_registrar_symbol(cnum)
+    }
+}
+
 /// Collect all `extern mod` directives in `c`, then
 /// try to install their targets, failing if any target
 /// can't be found.
-pub fn find_and_install_dependencies(context: &BuildContext,
-                                     parent: &CrateId,
-                                     parent_crate: &Path,
-                                     sess: session::Session,
-                                     exec: &mut workcache::Exec,
-                                     c: &ast::Crate,
-                                     deps: &mut DepMap,
-                                     save: |Path|) {
+pub fn find_and_install_dependencies(installer: &mut CrateInstaller,
+                                     c: &ast::Crate) {
     debug!("In find_and_install_dependencies...");
-    let mut visitor = ViewItemVisitor {
-        context: context,
-        parent: parent,
-        parent_crate: parent_crate,
-        sess: sess,
-        exec: exec,
-        c: c,
-        save: save,
-        deps: deps
-    };
-    visit::walk_crate(&mut visitor, c, ())
+    visit::walk_crate(installer, c, ())
 }
 
 pub fn mk_string_lit(s: @str) -> ast::Lit {
index c52ff2d088d13a767a470b043b4ccdffe1b315b6..546f555038756b1dfd58c7c19bb82acb81c0c0f3 100644 (file)
@@ -521,7 +521,8 @@ fn test_ascii() {
 
     #[test]
     fn test_ascii_vec() {
-        assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59]));
+        let test = &[40u8, 32u8, 59u8];
+        assert_eq!(test.to_ascii(), v2ascii!([40, 32, 59]));
         assert_eq!("( ;".to_ascii(),                 v2ascii!([40, 32, 59]));
         // FIXME: #5475 borrowchk error, owned vectors do not live long enough
         // if chained-from directly
@@ -587,14 +588,18 @@ fn test_opt() {
 
         assert_eq!("zoä华".to_ascii_opt(), None);
 
-        assert_eq!((&[127u8, 128u8, 255u8]).to_ascii_opt(), None);
+        let test1 = &[127u8, 128u8, 255u8];
+        assert_eq!((test1).to_ascii_opt(), None);
 
         let v = [40u8, 32u8, 59u8];
-        assert_eq!(v.to_ascii_opt(), Some(v2ascii!(&[40, 32, 59])));
+        let v2 = v2ascii!(&[40, 32, 59]);
+        assert_eq!(v.to_ascii_opt(), Some(v2));
         let v = [127u8, 128u8, 255u8];
         assert_eq!(v.to_ascii_opt(), None);
 
-        assert_eq!("( ;".to_ascii_opt(), Some(v2ascii!(&[40, 32, 59])));
+        let v = "( ;";
+        let v2 = v2ascii!(&[40, 32, 59]);
+        assert_eq!(v.to_ascii_opt(), Some(v2));
         assert_eq!("zoä华".to_ascii_opt(), None);
 
         assert_eq!((~[40u8, 32u8, 59u8]).into_ascii_opt(), Some(v2ascii!(~[40, 32, 59])));
index aedda59bbac1bd9ce5fe03603dc1702f4f11ab03..18cb470db4da24fb08c7de265546c92cca860a89 100644 (file)
@@ -68,6 +68,7 @@ pub fn append<T:Clone>(lhs: @[T], rhs: &[T]) -> @[T] {
 
 
 /// Apply a function to each element of a vector and return the results
+#[inline]
 pub fn map<T, U>(v: &[T], f: |x: &T| -> U) -> @[U] {
     build(Some(v.len()), |push| {
         for elem in v.iter() {
@@ -82,6 +83,7 @@ pub fn map<T, U>(v: &[T], f: |x: &T| -> U) -> @[U] {
  * Creates an immutable vector of size `n_elts` and initializes the elements
  * to the value returned by the function `op`.
  */
+#[inline]
 pub fn from_fn<T>(n_elts: uint, op: |uint| -> T) -> @[T] {
     build(Some(n_elts), |push| {
         let mut i: uint = 0u;
@@ -95,6 +97,7 @@ pub fn from_fn<T>(n_elts: uint, op: |uint| -> T) -> @[T] {
  * Creates an immutable vector of size `n_elts` and initializes the elements
  * to the value `t`.
  */
+#[inline]
 pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> @[T] {
     build(Some(n_elts), |push| {
         let mut i: uint = 0u;
@@ -109,6 +112,7 @@ pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> @[T] {
  * Creates and initializes an immutable managed vector by moving all the
  * elements from an owned vector.
  */
+#[inline]
 pub fn to_managed_move<T>(v: ~[T]) -> @[T] {
     let mut av = @[];
     unsafe {
@@ -124,6 +128,7 @@ pub fn to_managed_move<T>(v: ~[T]) -> @[T] {
  * Creates and initializes an immutable managed vector by copying all the
  * elements of a slice.
  */
+#[inline]
 pub fn to_managed<T:Clone>(v: &[T]) -> @[T] {
     from_fn(v.len(), |i| v[i].clone())
 }
@@ -135,6 +140,7 @@ fn clone(&self) -> @[T] {
 }
 
 impl<A> FromIterator<A> for @[A] {
+    #[inline]
     fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> @[A] {
         let (lower, _) = iterator.size_hint();
         build(Some(lower), |push| {
@@ -216,6 +222,7 @@ unsafe fn push_fast<T>(v: &mut @[T], initval: T) {
         move_val_init(&mut(*p), initval);
     }
 
+    #[inline]
     unsafe fn push_slow<T>(v: &mut @[T], initval: T) {
         reserve_at_least(v, v.len() + 1u);
         push_fast(v, initval);
@@ -232,6 +239,7 @@ unsafe fn push_slow<T>(v: &mut @[T], initval: T) {
      * * v - A vector
      * * n - The number of elements to reserve space for
      */
+    #[inline]
     pub unsafe fn reserve<T>(v: &mut @[T], n: uint) {
         // Only make the (slow) call into the runtime if we have to
         if capacity(*v) < n {
@@ -243,6 +251,7 @@ pub unsafe fn reserve<T>(v: &mut @[T], n: uint) {
 
     // Implementation detail. Shouldn't be public
     #[allow(missing_doc)]
+    #[inline]
     pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut Box<Vec<()>>, n: uint) {
         // check for `uint` overflow
         unsafe {
@@ -257,6 +266,7 @@ pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut Box<Vec<()>>, n: uint) {
             }
         }
 
+        #[inline]
         fn local_realloc(ptr: *(), size: uint) -> *() {
             use rt::local::Local;
             use rt::task::Task;
@@ -281,6 +291,7 @@ fn local_realloc(ptr: *(), size: uint) -> *() {
      * * v - A vector
      * * n - The number of elements to reserve space for
      */
+    #[inline]
     pub unsafe fn reserve_at_least<T>(v: &mut @[T], n: uint) {
         reserve(v, uint::next_power_of_two(n));
     }
index fd9040423a3d9517e73422262798c9980ae8314d..ab374ebccfeccb25f9ff43e65c9a1d49a02a8ad3 100644 (file)
@@ -17,6 +17,8 @@
 
 type DropGlue<'a> = 'a |**TyDesc, *c_void|;
 
+static RC_IMMORTAL : uint = 0x77777777;
+
 /*
  * Box annihilation
  *
 
 struct AnnihilateStats {
     n_total_boxes: uint,
-    n_unique_boxes: uint,
     n_bytes_freed: uint
 }
 
 unsafe fn each_live_alloc(read_next_before: bool,
-                          f: |alloc: *mut raw::Box<()>, uniq: bool| -> bool)
+                          f: |alloc: *mut raw::Box<()>| -> bool)
                           -> bool {
     //! Walks the internal list of allocations
 
-    use managed;
     use rt::local_heap;
 
     let mut alloc = local_heap::live_allocs();
     while alloc != ptr::mut_null() {
         let next_before = (*alloc).next;
-        let uniq = (*alloc).ref_count == managed::RC_MANAGED_UNIQUE;
 
-        if !f(alloc, uniq) {
+        if !f(alloc) {
             return false;
         }
 
@@ -70,11 +69,9 @@ fn debug_mem() -> bool {
 pub unsafe fn annihilate() {
     use rt::local_heap::local_free;
     use mem;
-    use managed;
 
     let mut stats = AnnihilateStats {
         n_total_boxes: 0,
-        n_unique_boxes: 0,
         n_bytes_freed: 0
     };
 
@@ -82,13 +79,9 @@ pub unsafe fn annihilate() {
     //
     // In this pass, nothing gets freed, so it does not matter whether
     // we read the next field before or after the callback.
-    each_live_alloc(true, |alloc, uniq| {
+    each_live_alloc(true, |alloc| {
         stats.n_total_boxes += 1;
-        if uniq {
-            stats.n_unique_boxes += 1;
-        } else {
-            (*alloc).ref_count = managed::RC_IMMORTAL;
-        }
+        (*alloc).ref_count = RC_IMMORTAL;
         true
     });
 
@@ -97,12 +90,10 @@ pub unsafe fn annihilate() {
     // In this pass, unique-managed boxes may get freed, but not
     // managed boxes, so we must read the `next` field *after* the
     // callback, as the original value may have been freed.
-    each_live_alloc(false, |alloc, uniq| {
-        if !uniq {
-            let tydesc = (*alloc).type_desc;
-            let data = &(*alloc).data as *();
-            ((*tydesc).drop_glue)(data as *i8);
-        }
+    each_live_alloc(false, |alloc| {
+        let tydesc = (*alloc).type_desc;
+        let data = &(*alloc).data as *();
+        ((*tydesc).drop_glue)(data as *i8);
         true
     });
 
@@ -112,13 +103,11 @@ pub unsafe fn annihilate() {
     // unique-managed boxes, though I think that none of those are
     // left), so we must read the `next` field before, since it will
     // not be valid after.
-    each_live_alloc(true, |alloc, uniq| {
-        if !uniq {
-            stats.n_bytes_freed +=
-                (*((*alloc).type_desc)).size
-                + mem::size_of::<raw::Box<()>>();
-            local_free(alloc as *i8);
-        }
+    each_live_alloc(true, |alloc| {
+        stats.n_bytes_freed +=
+            (*((*alloc).type_desc)).size
+            + mem::size_of::<raw::Box<()>>();
+        local_free(alloc as *i8);
         true
     });
 
@@ -126,8 +115,7 @@ pub unsafe fn annihilate() {
         // We do logging here w/o allocation.
         debug!("annihilator stats:\n  \
                        total boxes: {}\n  \
-                      unique boxes: {}\n  \
                        bytes freed: {}",
-                stats.n_total_boxes, stats.n_unique_boxes, stats.n_bytes_freed);
+                stats.n_total_boxes, stats.n_bytes_freed);
     }
 }
index bf37e5fca6a5f3061452edf0f50fdc8a6ab6962f..985a387ee2baacbcae023ffc2b1740c5bd45206b 100644 (file)
@@ -251,6 +251,7 @@ mod $name {
             #[allow(unused_imports)];
 
             use native;
+            use comm::*;
             use prelude::*;
             use super::*;
             use super::super::*;
@@ -323,6 +324,20 @@ pub struct SharedChan<T> {
     priv queue: mpsc::Producer<T, Packet>,
 }
 
+/// This enumeration is the list of the possible reasons that try_recv could not
+/// return data when called.
+#[deriving(Eq, Clone)]
+pub enum TryRecvResult<T> {
+    /// This channel is currently empty, but the sender(s) have not yet
+    /// disconnected, so data may yet become available.
+    Empty,
+    /// This channel's sending half has become disconnected, and there will
+    /// never be any more data received on this channel
+    Disconnected,
+    /// The channel had some data and we successfully popped it
+    Data(T),
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Internal struct definitions
 ///////////////////////////////////////////////////////////////////////////////
@@ -739,11 +754,11 @@ pub fn recv(&self) -> T {
     /// block on a port.
     ///
     /// This function cannot fail.
-    pub fn try_recv(&self) -> Option<T> {
+    pub fn try_recv(&self) -> TryRecvResult<T> {
         self.try_recv_inc(true)
     }
 
-    fn try_recv_inc(&self, increment: bool) -> Option<T> {
+    fn try_recv_inc(&self, increment: bool) -> TryRecvResult<T> {
         // This is a "best effort" situation, so if a queue is inconsistent just
         // don't worry about it.
         let this = unsafe { cast::transmute_mut(self) };
@@ -807,7 +822,35 @@ fn try_recv_inc(&self, increment: bool) -> Option<T> {
         if increment && ret.is_some() {
             unsafe { (*this.queue.packet()).steals += 1; }
         }
-        return ret;
+        match ret {
+            Some(t) => Data(t),
+            None => {
+                // It's possible that between the time that we saw the queue was
+                // empty and here the other side disconnected. It's also
+                // possible for us to see the disconnection here while there is
+                // data in the queue. It's pretty backwards-thinking to return
+                // Disconnected when there's actually data on the queue, so if
+                // we see a disconnected state be sure to check again to be 100%
+                // sure that there's no data in the queue.
+                let cnt = unsafe { (*this.queue.packet()).cnt.load(Relaxed) };
+                if cnt != DISCONNECTED { return Empty }
+
+                let ret = match this.queue {
+                    SPSC(ref mut queue) => queue.pop(),
+                    MPSC(ref mut queue) => match queue.pop() {
+                        mpsc::Data(t) => Some(t),
+                        mpsc::Empty => None,
+                        mpsc::Inconsistent => {
+                            fail!("inconsistent with no senders?!");
+                        }
+                    }
+                };
+                match ret {
+                    Some(data) => Data(data),
+                    None => Disconnected,
+                }
+            }
+        }
     }
 
     /// Attempt to wait for a value on this port, but does not fail if the
@@ -824,7 +867,11 @@ fn try_recv_inc(&self, increment: bool) -> Option<T> {
     /// the value found on the port is returned.
     pub fn recv_opt(&self) -> Option<T> {
         // optimistic preflight check (scheduling is expensive)
-        match self.try_recv() { None => {}, data => return data }
+        match self.try_recv() {
+            Empty => {},
+            Disconnected => return None,
+            Data(t) => return Some(t),
+        }
 
         let packet;
         let this;
@@ -843,12 +890,11 @@ pub fn recv_opt(&self) -> Option<T> {
             });
         }
 
-        let data = self.try_recv_inc(false);
-        if data.is_none() &&
-           unsafe { (*packet).cnt.load(SeqCst) } != DISCONNECTED {
-            fail!("bug: woke up too soon {}", unsafe { (*packet).cnt.load(SeqCst) });
+        match self.try_recv_inc(false) {
+            Data(t) => Some(t),
+            Empty => fail!("bug: woke up too soon"),
+            Disconnected => None,
         }
-        return data;
     }
 
     /// Returns an iterator which will block waiting for messages, but never
@@ -1005,7 +1051,10 @@ pub fn stress_factor() -> uint {
             for _ in range(0, AMT * NTHREADS) {
                 assert_eq!(p.recv(), 1);
             }
-            assert_eq!(p.try_recv(), None);
+            match p.try_recv() {
+                Data(..) => fail!(),
+                _ => {}
+            }
             c1.send(());
         }
 
@@ -1129,7 +1178,7 @@ fn no_runtime() {
     test!(fn oneshot_single_thread_try_recv_open() {
         let (port, chan) = Chan::<int>::new();
         chan.send(10);
-        assert!(port.try_recv() == Some(10));
+        assert!(port.recv_opt() == Some(10));
     })
 
     test!(fn oneshot_single_thread_try_recv_closed() {
@@ -1140,21 +1189,21 @@ fn no_runtime() {
 
     test!(fn oneshot_single_thread_peek_data() {
         let (port, chan) = Chan::<int>::new();
-        assert!(port.try_recv().is_none());
+        assert_eq!(port.try_recv(), Empty)
         chan.send(10);
-        assert!(port.try_recv().is_some());
+        assert_eq!(port.try_recv(), Data(10));
     })
 
     test!(fn oneshot_single_thread_peek_close() {
         let (port, chan) = Chan::<int>::new();
         { let _c = chan; }
-        assert!(port.try_recv().is_none());
-        assert!(port.try_recv().is_none());
+        assert_eq!(port.try_recv(), Disconnected);
+        assert_eq!(port.try_recv(), Disconnected);
     })
 
     test!(fn oneshot_single_thread_peek_open() {
-        let (port, _) = Chan::<int>::new();
-        assert!(port.try_recv().is_none());
+        let (port, _chan) = Chan::<int>::new();
+        assert_eq!(port.try_recv(), Empty);
     })
 
     test!(fn oneshot_multi_task_recv_then_send() {
@@ -1321,4 +1370,27 @@ fn recv(port: Port<~int>, i: int) {
         drop(chan);
         assert_eq!(count_port.recv(), 4);
     })
+
+    test!(fn try_recv_states() {
+        let (p, c) = Chan::<int>::new();
+        let (p1, c1) = Chan::<()>::new();
+        let (p2, c2) = Chan::<()>::new();
+        do spawn {
+            p1.recv();
+            c.send(1);
+            c2.send(());
+            p1.recv();
+            drop(c);
+            c2.send(());
+        }
+
+        assert_eq!(p.try_recv(), Empty);
+        c1.send(());
+        p2.recv();
+        assert_eq!(p.try_recv(), Data(1));
+        assert_eq!(p.try_recv(), Empty);
+        c1.send(());
+        p2.recv();
+        assert_eq!(p.try_recv(), Disconnected);
+    })
 }
index 302c9d9ea469be20b9ea917caf3ba1443d8d97e5..fa5ec1d3e309fc328b1e5146e3e679d9fd60ebc2 100644 (file)
@@ -45,6 +45,7 @@
 #[allow(dead_code)];
 
 use cast;
+use comm;
 use iter::Iterator;
 use kinds::Send;
 use ops::Drop;
@@ -279,7 +280,9 @@ pub fn recv(&mut self) -> T { self.port.recv() }
     pub fn recv_opt(&mut self) -> Option<T> { self.port.recv_opt() }
     /// Immediately attempt to receive a value on a port, this function will
     /// never block. Has the same semantics as `Port.try_recv`.
-    pub fn try_recv(&mut self) -> Option<T> { self.port.try_recv() }
+    pub fn try_recv(&mut self) -> comm::TryRecvResult<T> {
+        self.port.try_recv()
+    }
 }
 
 #[unsafe_destructor]
@@ -409,8 +412,8 @@ mod test {
             a = p1.recv() => { assert_eq!(a, 1); },
             a = p2.recv() => { assert_eq!(a, 2); }
         )
-        assert_eq!(p1.try_recv(), None);
-        assert_eq!(p2.try_recv(), None);
+        assert_eq!(p1.try_recv(), Empty);
+        assert_eq!(p2.try_recv(), Empty);
         c3.send(());
     })
 
index 4cbecc9b42f851e4cda79c97b733fe1255e870fb..9985a280fa5f152e51ae669df05c0cd620da7d41 100644 (file)
@@ -16,6 +16,8 @@
 
 */
 
+#[allow(experimental)];
+
 use kinds::Send;
 use clone::{Clone, DeepClone};
 use managed;
@@ -24,6 +26,9 @@
 #[lang="gc"]
 #[cfg(not(test))]
 #[no_send]
+#[experimental = "Gc is currently based on reference-counting and will not collect cycles until \
+                  task annihilation. For now, cycles need to be broken manually by using `Rc<T>` \
+                  with a non-owning `Weak<T>` pointer. A tracing garbage collector is planned."]
 pub struct Gc<T> {
     priv ptr: @T
 }
index 72f61a7bf84efa62271ce593df1a5b1ab07843e0..cc0cb6b3446e3b071d52accca3d86875d54dcdec 100644 (file)
@@ -370,13 +370,13 @@ fn push_bytes_fail_reset_len() {
             count: 0,
         };
         // FIXME (#7049): Figure out some other way to do this.
-        //let buf = @mut ~[8, 9];
+        //let buf = RefCell::new(~[8, 9]);
         (|| {
-            //reader.push_bytes(&mut *buf, 4);
+            //reader.push_bytes(buf.borrow_mut().get(), 4);
         }).finally(|| {
             // NB: Using rtassert here to trigger abort on failure since this is a should_fail test
             // FIXME: #7049 This fails because buf is still borrowed
-            //rtassert!(*buf == ~[8, 9, 10]);
+            //rtassert!(buf.borrow().get() == ~[8, 9, 10]);
         })
     }
 
index 660c3d3adbc7933bba6c8f5818ec63c1620a0bd3..6c380be343c889b585894904d2c42a88b8640401 100644 (file)
@@ -437,7 +437,8 @@ fn test_buf_reader() {
 
     #[test]
     fn test_read_char() {
-        let mut r = BufReader::new(bytes!("Việt"));
+        let b = bytes!("Việt");
+        let mut r = BufReader::new(b);
         assert_eq!(r.read_char(), Some('V'));
         assert_eq!(r.read_char(), Some('i'));
         assert_eq!(r.read_char(), Some('ệ'));
@@ -447,7 +448,8 @@ fn test_read_char() {
 
     #[test]
     fn test_read_bad_char() {
-        let mut r = BufReader::new(bytes!(0x80));
+        let b = bytes!(0x80);
+        let mut r = BufReader::new(b);
         assert_eq!(r.read_char(), None);
     }
 
index 6515cbc5fb3e27a02690cf5892219ed0056dc61b..41cce58d9d59faf6b0101405c04b8244f40fc57d 100644 (file)
@@ -1062,7 +1062,7 @@ impl<T: Reader + Writer> Stream for T {}
 /// Raises the same conditions as the `read` method except for `EndOfFile`
 /// which is swallowed.
 /// Iteration yields `None` if the condition is handled.
-struct LineIterator<'r, T> {
+pub struct LineIterator<'r, T> {
     priv buffer: &'r mut T,
 }
 
index a8b7e8e00ead01139d0fbfeca6203c13729881d1..4c8a640a849c12f3b92b8ccb03d96046135fb5ab 100644 (file)
@@ -181,7 +181,7 @@ mod tests {
         let io = ~[];
         let args = ProcessConfig {
             program: "/bin/sh",
-            args: [~"-c", ~"true"],
+            args: &[~"-c", ~"true"],
             env: None,
             cwd: None,
             io: io,
@@ -198,7 +198,7 @@ mod tests {
         let io = ~[];
         let args = ProcessConfig {
             program: "if-this-is-a-binary-then-the-world-has-ended",
-            args: [],
+            args: &[],
             env: None,
             cwd: None,
             io: io,
@@ -215,7 +215,7 @@ mod tests {
         let io = ~[];
         let args = ProcessConfig {
             program: "/bin/sh",
-            args: [~"-c", ~"exit 1"],
+            args: &[~"-c", ~"exit 1"],
             env: None,
             cwd: None,
             io: io,
@@ -231,7 +231,7 @@ mod tests {
         let io = ~[];
         let args = ProcessConfig {
             program: "/bin/sh",
-            args: [~"-c", ~"kill -1 $$"],
+            args: &[~"-c", ~"kill -1 $$"],
             env: None,
             cwd: None,
             io: io,
@@ -274,7 +274,7 @@ pub fn run_output(args: ProcessConfig) -> ~str {
         let io = ~[Ignored, CreatePipe(false, true)];
         let args = ProcessConfig {
             program: "/bin/sh",
-            args: [~"-c", ~"echo foobar"],
+            args: &[~"-c", ~"echo foobar"],
             env: None,
             cwd: None,
             io: io,
@@ -289,7 +289,7 @@ pub fn run_output(args: ProcessConfig) -> ~str {
         let cwd = Some("/");
         let args = ProcessConfig {
             program: "/bin/sh",
-            args: [~"-c", ~"pwd"],
+            args: &[~"-c", ~"pwd"],
             env: None,
             cwd: cwd,
             io: io,
@@ -304,7 +304,7 @@ pub fn run_output(args: ProcessConfig) -> ~str {
                    CreatePipe(false, true)];
         let args = ProcessConfig {
             program: "/bin/sh",
-            args: [~"-c", ~"read line; echo $line"],
+            args: &[~"-c", ~"read line; echo $line"],
             env: None,
             cwd: None,
             io: io,
index 34b4ed5e1ef453ecf9887b6ed6b61d92b1d4c337..0f05254b034896dc99a9efda17064e09ffa1b73a 100644 (file)
@@ -144,6 +144,7 @@ pub fn unregister(&mut self, signum: Signum) {
 #[cfg(test)]
 mod test {
     use libc;
+    use comm::Empty;
     use io::timer;
     use super::{Listener, Interrupt};
 
@@ -194,7 +195,7 @@ fn test_io_signal_unregister() {
         s2.unregister(Interrupt);
         sigint();
         timer::sleep(10);
-        assert!(s2.port.try_recv().is_none());
+        assert_eq!(s2.port.try_recv(), Empty);
     }
 
     #[cfg(windows)]
index 7c9aa28bfe9a8008aa3fa6c6472248911498ddc4..d156a7460e17c30fabff087211c9b92f7d8bd408 100644 (file)
@@ -123,7 +123,7 @@ fn oneshot_twice() {
         let port1 = timer.oneshot(10000);
         let port = timer.oneshot(1);
         port.recv();
-        assert_eq!(port1.try_recv(), None);
+        assert!(port1.recv_opt().is_none());
     }
 
     #[test]
@@ -131,8 +131,7 @@ fn test_io_timer_oneshot_then_sleep() {
         let mut timer = Timer::new().unwrap();
         let port = timer.oneshot(100000000000);
         timer.sleep(1); // this should invalidate the port
-
-        assert_eq!(port.try_recv(), None);
+        assert!(port.recv_opt().is_none());
     }
 
     #[test]
index 2056f8b33ec1d5c93c9e4cda44a4ddef6a35c978..fcf0f4f24443c7e0bcf577047dd349c38ab955d8 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -1362,6 +1362,12 @@ pub fn peek(&'a mut self) -> Option<&'a A> {
             None => None,
         }
     }
+
+    /// Check whether peekable iterator is empty or not.
+    #[inline]
+    pub fn is_empty(&mut self) -> bool {
+        self.peek().is_some()
+    }
 }
 
 /// An iterator which rejects elements while `predicate` is true
@@ -2923,4 +2929,12 @@ fn test_reverse() {
         ys.mut_iter().reverse_();
         assert_eq!(ys, [5, 4, 3, 2, 1]);
     }
+
+    fn test_peekable_is_empty() {
+        let a = [1];
+        let mut it = a.iter().peekable();
+        assert!( !it.is_empty() );
+        it.next();
+        assert!( it.is_empty() );
+    }
 }
index ac4be8fec93e43535d4c827c2aab74a2ebe5cbab..9cf94e5a1b894ddbb348f709d16d510c0f1770fd 100644 (file)
 pub use libc::funcs::c95::stdio::{fwrite, perror, puts, remove, rewind};
 pub use libc::funcs::c95::stdio::{setbuf, setvbuf, tmpfile, ungetc};
 
-pub use libc::funcs::c95::stdlib::{abort, abs, atof, atoi, calloc, exit};
+pub use libc::funcs::c95::stdlib::{abs, atof, atoi, calloc, exit};
 pub use libc::funcs::c95::stdlib::{free, getenv, labs, malloc, rand};
 pub use libc::funcs::c95::stdlib::{realloc, srand, strtod, strtol};
 pub use libc::funcs::c95::stdlib::{strtoul, system};
@@ -194,8 +194,19 @@ pub mod c95 {
             This type is only useful as a pointer target. Do not use it as a
             return type for FFI functions which have the `void` return type in
             C. Use the unit type `()` or omit the return type instead.
+
+            For LLVM to recognize the void pointer type and by extension
+            functions like malloc(), we need to have it represented as i8* in
+            LLVM bitcode. The enum used here ensures this and prevents misuse
+            of the "raw" type by only having private variants.. We need two
+            variants, because the compiler complains about the repr attribute
+            otherwise.
             */
-            pub enum c_void {}
+            #[repr(u8)]
+            pub enum c_void {
+                priv variant1,
+                priv variant2
+            }
             pub enum FILE {}
             pub enum fpos_t {}
         }
@@ -3215,7 +3226,6 @@ pub fn strtoul(s: *c_char, endp: **c_char, base: c_int)
                 pub fn malloc(size: size_t) -> *c_void;
                 pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
                 pub fn free(p: *c_void);
-                pub fn abort() -> !;
                 pub fn exit(status: c_int) -> !;
                 // Omitted: atexit.
                 pub fn system(s: *c_char) -> c_int;
index 95fdce99ea654aceea5cf7e5d4033a6a8121bc2d..7ef7a256c1694256e1b80e3257f5bf7f80679868 100644 (file)
@@ -187,8 +187,7 @@ pub fn get<T: 'static, U>(key: Key<T>, f: |Option<&T>| -> U) -> U {
 /// if the key provided is not present in TLS currently.
 ///
 /// It is considered a runtime error to attempt to get a value which is already
-/// on loan via this or the `get` methods. This is similar to how it's a runtime
-/// error to take two mutable loans on an `@mut` box.
+/// on loan via this or the `get` methods.
 pub fn get_mut<T: 'static, U>(key: Key<T>, f: |Option<&mut T>| -> U) -> U {
     get_with(key, MutLoan, |x| {
         match x {
@@ -281,7 +280,8 @@ fn get_with<T:'static,
 }
 
 fn abort() -> ! {
-    unsafe { libc::abort() }
+    use std::unstable::intrinsics;
+    unsafe { intrinsics::abort() }
 }
 
 /// Inserts a value into task local storage. If the key is already present in
index c5705665896f1022258a562f6de57064c507e25f..914cc25250c7f6a5ab087b7d53ce8c430a738541 100644 (file)
@@ -14,9 +14,6 @@
 
 #[cfg(not(test))] use cmp::*;
 
-pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
-pub static RC_IMMORTAL : uint = 0x77777777;
-
 /// Returns the refcount of a shared box (as just before calling this)
 #[inline]
 pub fn refcount<T>(t: @T) -> uint {
index beecf8a44f6325d4c86aead191690df05122cc39..a8eaa895650844d02364e8d6ca9ddd143e689234 100644 (file)
@@ -17,7 +17,7 @@
 use default::Default;
 use libc::{c_float, c_int};
 use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal};
-use num::{Zero, One, strconv};
+use num::{Zero, One, Bounded, strconv};
 use num;
 use to_str;
 use unstable::intrinsics;
index 6a266c6c59f7ac4f1305de6fda9ac0ea1383cbb7..fe51cb07646ec54e142ddadfbd1f07aab5a09347 100644 (file)
@@ -18,7 +18,7 @@
 use default::Default;
 use libc::{c_double, c_int};
 use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal};
-use num::{Zero, One, strconv};
+use num::{Zero, One, Bounded, strconv};
 use num;
 use to_str;
 use unstable::intrinsics;
index 5f431dfdf04272730bb9cc200167dc94b3c298ef..e19e7c6c3b8bd2109c75c6c931f09d70e058d06d 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::*;
 
 use default::Default;
-use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul};
+use num::{Bitwise, Bounded, CheckedAdd, CheckedSub, CheckedMul};
 use num::{CheckedDiv, Zero, One, strconv};
 use num::{ToStrRadix, FromStrRadix};
 use option::{Option, Some, None};
@@ -24,7 +24,7 @@
 
 int_module!(i16, 16)
 
-impl BitCount for i16 {
+impl Bitwise for i16 {
     /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
     #[inline]
     fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } }
index 8bb03344923def2900b8cc9154d9f538b353347c..372d9f680d72e7501429d3220813cc32cf5d2dec 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::*;
 
 use default::Default;
-use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul};
+use num::{Bitwise, Bounded, CheckedAdd, CheckedSub, CheckedMul};
 use num::{CheckedDiv, Zero, One, strconv};
 use num::{ToStrRadix, FromStrRadix};
 use option::{Option, Some, None};
@@ -24,7 +24,7 @@
 
 int_module!(i32, 32)
 
-impl BitCount for i32 {
+impl Bitwise for i32 {
     /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
     #[inline]
     fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } }
index 891043ad5f82d5e6f74b258a9be09f5107d594e9..2a91ee4dd71cc383efd91c5328aaac6470d1cb04 100644 (file)
@@ -17,7 +17,7 @@
 use default::Default;
 #[cfg(target_word_size = "64")]
 use num::CheckedMul;
-use num::{BitCount, CheckedAdd, CheckedSub};
+use num::{Bitwise, Bounded, CheckedAdd, CheckedSub};
 use num::{CheckedDiv, Zero, One, strconv};
 use num::{ToStrRadix, FromStrRadix};
 use option::{Option, Some, None};
@@ -26,7 +26,7 @@
 
 int_module!(i64, 64)
 
-impl BitCount for i64 {
+impl Bitwise for i64 {
     /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
     #[inline]
     fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } }
index fd123ec57cc743557f8a1ad075251d014d0b1bdd..66162ce350269b07942c13575c20114a3533789e 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::*;
 
 use default::Default;
-use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul};
+use num::{Bitwise, Bounded, CheckedAdd, CheckedSub, CheckedMul};
 use num::{CheckedDiv, Zero, One, strconv};
 use num::{ToStrRadix, FromStrRadix};
 use option::{Option, Some, None};
@@ -24,7 +24,7 @@
 
 int_module!(i8, 8)
 
-impl BitCount for i8 {
+impl Bitwise for i8 {
     /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
     #[inline]
     fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } }
index 123555e4a63d86f2a5306ee26152d70de68ff2bd..8068d4a74cbf8ae5e978fe4bd97d29e600fed96d 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::*;
 
 use default::Default;
-use num::{BitCount, CheckedAdd, CheckedSub, CheckedMul};
+use num::{Bitwise, Bounded, CheckedAdd, CheckedSub, CheckedMul};
 use num::{CheckedDiv, Zero, One, strconv};
 use num::{ToStrRadix, FromStrRadix};
 use option::{Option, Some, None};
@@ -26,7 +26,7 @@
 #[cfg(target_word_size = "64")] int_module!(int, 64)
 
 #[cfg(target_word_size = "32")]
-impl BitCount for int {
+impl Bitwise for int {
     /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
     #[inline]
     fn population_count(&self) -> int { (*self as i32).population_count() as int }
@@ -41,7 +41,7 @@ fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int }
 }
 
 #[cfg(target_word_size = "64")]
-impl BitCount for int {
+impl Bitwise for int {
     /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
     #[inline]
     fn population_count(&self) -> int { (*self as i64).population_count() as int }
index 0e7e4277dd6cd2a2fb836b80a7dae2eb7e7e9bd9..add0991f7afb9b76c285bb1c2e06b9bebea3c8b3 100644 (file)
@@ -308,15 +308,13 @@ fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 }
 
     /// Returns `true` if the number is divisible by `2`
     #[inline]
-    fn is_even(&self) -> bool { self.is_multiple_of(&2) }
+    fn is_even(&self) -> bool { self & 1 == 0 }
 
     /// Returns `true` if the number is not divisible by `2`
     #[inline]
     fn is_odd(&self) -> bool { !self.is_even() }
 }
 
-impl Bitwise for $T {}
-
 #[cfg(not(test))]
 impl BitOr<$T,$T> for $T {
     #[inline]
@@ -446,6 +444,7 @@ mod tests {
     use i32;
     use num;
     use num::CheckedDiv;
+    use num::Bitwise;
     use mem;
 
     #[test]
index 2bf3158e6b4355c866bb06b0c3201945a9eb1d7e..05f21c7d44804ed2d984b0ea926d55b270ac39e6 100644 (file)
@@ -324,21 +324,27 @@ pub trait Real: Signed
 /// Inverse hyperbolic tangent function.
 #[inline(always)] pub fn atanh<T: Real>(value: T) -> T { value.atanh() }
 
-/// Collects the bitwise operators under one trait.
-pub trait Bitwise: Not<Self>
+pub trait Bounded {
+    // FIXME (#5527): These should be associated constants
+    fn min_value() -> Self;
+    fn max_value() -> Self;
+}
+
+/// Numbers with a fixed binary representation.
+pub trait Bitwise: Bounded
+                 + Not<Self>
                  + BitAnd<Self,Self>
                  + BitOr<Self,Self>
                  + BitXor<Self,Self>
                  + Shl<Self,Self>
-                 + Shr<Self,Self> {}
-
-/// A trait for common counting operations on bits.
-pub trait BitCount {
+                 + Shr<Self,Self> {
     /// Returns the number of bits set in the number.
     ///
     /// # Example
     ///
     /// ```rust
+    /// use std::num::Bitwise;
+    ///
     /// let n = 0b0101000u16;
     /// assert_eq!(n.population_count(), 2);
     /// ```
@@ -348,6 +354,8 @@ pub trait BitCount {
     /// # Example
     ///
     /// ```rust
+    /// use std::num::Bitwise;
+    ///
     /// let n = 0b0101000u16;
     /// assert_eq!(n.leading_zeros(), 10);
     /// ```
@@ -357,18 +365,14 @@ pub trait BitCount {
     /// # Example
     ///
     /// ```rust
+    /// use std::num::Bitwise;
+    ///
     /// let n = 0b0101000u16;
     /// assert_eq!(n.trailing_zeros(), 3);
     /// ```
     fn trailing_zeros(&self) -> Self;
 }
 
-pub trait Bounded {
-    // FIXME (#5527): These should be associated constants
-    fn min_value() -> Self;
-    fn max_value() -> Self;
-}
-
 /// Specifies the available operations common to all of Rust's core numeric primitives.
 /// These may not always make sense from a purely mathematical point of view, but
 /// may be useful for systems programming.
@@ -394,8 +398,7 @@ pub trait Primitive: Clone
 /// A collection of traits relevant to primitive signed and unsigned integers
 pub trait Int: Integer
              + Primitive
-             + Bitwise
-             + BitCount {}
+             + Bitwise {}
 
 /// Used for representing the classification of floating point numbers
 #[deriving(Eq)]
index 7e4145fc723db5e42cd84ca8c3d343237d50d1e3..770db889af55f1cd915462089780275beb4378a7 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::*;
 
 use default::Default;
-use num::BitCount;
+use num::{Bitwise, Bounded};
 use num::{CheckedAdd, CheckedSub, CheckedMul};
 use num::{CheckedDiv, Zero, One, strconv};
 use num::{ToStrRadix, FromStrRadix};
index 34c2a892d56b76d9ecb0c96ac3c6a6cd3d5908b8..9e08ffed3b70bbd3c7d80e649f360f7c24bad179 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::*;
 
 use default::Default;
-use num::BitCount;
+use num::{Bitwise, Bounded};
 use num::{CheckedAdd, CheckedSub, CheckedMul};
 use num::{CheckedDiv, Zero, One, strconv};
 use num::{ToStrRadix, FromStrRadix};
index c307b038627f99f1c8673ce7aedbcb4a7e8ffb5b..a579e7ebbbe4af52eb72a96df3e20d69179abd13 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::*;
 
 use default::Default;
-use num::BitCount;
+use num::{Bitwise, Bounded};
 #[cfg(target_word_size = "64")]
 use num::CheckedMul;
 use num::{CheckedAdd, CheckedSub};
index 06bda72c5fe6d8288dfac821b6aef5156084cf7a..4aa34b6d880444a08b14e75ac08c91158bf25c70 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::*;
 
 use default::Default;
-use num::BitCount;
+use num::{Bitwise, Bounded};
 use num::{CheckedAdd, CheckedSub, CheckedMul};
 use num::{CheckedDiv, Zero, One, strconv};
 use num::{ToStrRadix, FromStrRadix};
index a752cd938ba0de30cf25aae485a1538bd81079bd..d304f947542143c8f8e48a10019af03a60ee2673 100644 (file)
@@ -16,7 +16,7 @@
 
 use default::Default;
 use mem;
-use num::BitCount;
+use num::{Bitwise, Bounded};
 use num::{CheckedAdd, CheckedSub, CheckedMul};
 use num::{CheckedDiv, Zero, One, strconv};
 use num::{ToStrRadix, FromStrRadix};
index 1a256981d74ee0c8f9e9685379c65a54352ffe44..97e547a2d42802beaf5de1173cdab525f85eb82f 100644 (file)
@@ -169,15 +169,13 @@ fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 }
 
     /// Returns `true` if the number is divisible by `2`
     #[inline]
-    fn is_even(&self) -> bool { self.is_multiple_of(&2) }
+    fn is_even(&self) -> bool { self & 1 == 0 }
 
     /// Returns `true` if the number is not divisible by `2`
     #[inline]
     fn is_odd(&self) -> bool { !self.is_even() }
 }
 
-impl Bitwise for $T {}
-
 #[cfg(not(test))]
 impl BitOr<$T,$T> for $T {
     #[inline]
@@ -298,7 +296,7 @@ fn bytes(_: Option<$T>) -> uint { bits / 8 }
     fn is_signed(_: Option<$T>) -> bool { false }
 }
 
-impl BitCount for $T {
+impl Bitwise for $T {
     /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
     #[inline]
     fn population_count(&self) -> $T {
@@ -325,6 +323,7 @@ mod tests {
 
     use num;
     use num::CheckedDiv;
+    use num::Bitwise;
     use mem;
     use u16;
 
index bdec67e5d9f96c6f160d69ed2a5b38a632514580..aab98f19e151327cb098064d45822bf7f6c9cac9 100644 (file)
@@ -48,6 +48,7 @@
 use str::OwnedStr;
 use to_str::ToStr;
 use util;
+use vec;
 
 /// The option type
 #[deriving(Clone, DeepClone, Eq, Ord, TotalEq, TotalOrd, ToStr)]
@@ -98,6 +99,24 @@ pub fn as_mut<'r>(&'r mut self) -> Option<&'r mut T> {
         match *self { Some(ref mut x) => Some(x), None => None }
     }
 
+    /// Convert from `Option<T>` to `&[T]` (without copying)
+    #[inline]
+    pub fn as_slice<'r>(&'r self) -> &'r [T] {
+        match *self {
+            Some(ref x) => vec::ref_slice(x),
+            None => &[]
+        }
+    }
+
+    /// Convert from `Option<T>` to `&[T]` (without copying)
+    #[inline]
+    pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] {
+        match *self {
+            Some(ref mut x) => vec::mut_ref_slice(x),
+            None => &mut []
+        }
+    }
+
     /////////////////////////////////////////////////////////////////////////
     // Getting to contained values
     /////////////////////////////////////////////////////////////////////////
index 7b94de6c094d6d6a681ff0a9305adc4f07ae8e6b..e2ddabc1714b6f8f0b1cac84bf7fb8db7cfedc22 100644 (file)
@@ -237,7 +237,10 @@ fn is_ancestor_of(&self, other: &Path) -> bool {
             let mut ita = self.components();
             let mut itb = other.components();
             if bytes!(".") == self.repr {
-                return itb.next() != Some(bytes!(".."));
+                return match itb.next() {
+                    None => true,
+                    Some(b) => b != bytes!("..")
+                };
             }
             loop {
                 match (ita.next(), itb.next()) {
@@ -463,7 +466,10 @@ macro_rules! t(
 
     macro_rules! b(
         ($($arg:expr),+) => (
-            bytes!($($arg),+)
+            {
+                static the_bytes: &'static [u8] = bytes!($($arg),+);
+                the_bytes
+            }
         )
     )
 
@@ -689,7 +695,8 @@ macro_rules! t(
             );
             (v: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    let path = Path::new($path);
+                    let arg = $path;
+                    let path = Path::new(arg);
                     assert_eq!(path.$op(), $exp);
                 }
             );
index 09b00be7e9d61dfd52c6a220f0d7b7f49534ac9e..a42fdabef88927e308b79c2f59852de4e20e506c 100644 (file)
@@ -261,8 +261,13 @@ fn append_path(me: &mut Path, path: &str) {
             let mut s = str::with_capacity(me.repr.len() + 1 + pathlen);
             s.push_str(me.repr);
             let plen = me.prefix_len();
-            if !(me.repr.len() > plen && me.repr[me.repr.len()-1] == sep as u8) {
-                s.push_char(sep);
+            // if me is "C:" we don't want to add a path separator
+            match me.prefix {
+                Some(DiskPrefix) if me.repr.len() == plen => (),
+                _ if !(me.repr.len() > plen && me.repr[me.repr.len()-1] == sep as u8) => {
+                    s.push_char(sep);
+                }
+                _ => ()
             }
             match path_ {
                 None => s.push_str(path),
@@ -1074,7 +1079,10 @@ macro_rules! t(
 
     macro_rules! b(
         ($($arg:expr),+) => (
-            bytes!($($arg),+)
+            {
+                static the_bytes: &'static [u8] = bytes!($($arg),+);
+                the_bytes
+            }
         )
     )
 
@@ -1372,20 +1380,23 @@ fn test_components() {
         macro_rules! t(
             (s: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    let path = Path::new($path);
+                    let path = $path;
+                    let path = Path::new(path);
                     assert_eq!(path.$op(), Some($exp));
                 }
             );
             (s: $path:expr, $op:ident, $exp:expr, opt) => (
                 {
-                    let path = Path::new($path);
+                    let path = $path;
+                    let path = Path::new(path);
                     let left = path.$op();
                     assert_eq!(left, $exp);
                 }
             );
             (v: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    let path = Path::new($path);
+                    let path = $path;
+                    let path = Path::new(path);
                     assert_eq!(path.$op(), $exp);
                 }
             )
@@ -1549,6 +1560,8 @@ macro_rules! t(
         t!(s: "C:a\\b\\c", "C:d", "C:a\\b\\c\\d");
         t!(s: "C:a\\b", "..\\..\\..\\c", "C:..\\c");
         t!(s: "C:\\a\\b", "..\\..\\..\\c", "C:\\c");
+        t!(s: "C:", r"a\b\c", r"C:a\b\c");
+        t!(s: "C:", r"..\a", r"C:..\a");
         t!(s: "\\\\server\\share\\foo", "bar", "\\\\server\\share\\foo\\bar");
         t!(s: "\\\\server\\share\\foo", "..\\..\\bar", "\\\\server\\share\\bar");
         t!(s: "\\\\server\\share\\foo", "C:baz", "C:baz");
index 9045bafbe4591bbd0260fbf8d1fd52f6bac0463c..2f5f3e8f4568d0b045d055cfe690921f4b20bd2a 100644 (file)
@@ -58,8 +58,7 @@
 pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator};
 pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
 pub use num::Times;
-pub use num::{Bitwise, BitCount, Bounded, Integer, Real};
-pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
+pub use num::{Integer, Real, Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
 pub use num::{Orderable, Signed, Unsigned, Round};
 pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive};
 pub use path::{GenericPath, Path, PosixPath, WindowsPath};
index 9947d8822ae65a67427ae3301dbacdb3a9ccd071..48e796f0f4a53941a8fd87e90f63832688d14d9c 100644 (file)
@@ -230,4 +230,12 @@ fn test_dead() {
         drop(x);
         assert!(y.upgrade().is_none());
     }
+
+    #[test]
+    fn gc_inside() {
+        // see issue #11532
+        use gc::Gc;
+        let a = Rc::new(RefCell::new(Gc::new(1)));
+        assert!(a.borrow().try_borrow_mut().is_some());
+    }
 }
index 8a3e60eb3e2d521dc9da6356a47d49c6f7a6439b..e619e404dac86050c5128fd8ddbf5aaba7253c98 100644 (file)
@@ -227,13 +227,6 @@ fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         true
     }
 
-    fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~u8>();
-        if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
-        self.bump_past::<~u8>();
-        true
-    }
-
     fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<*u8>();
         if ! self.inner.visit_ptr(mtbl, inner) { return false; }
@@ -275,13 +268,6 @@ fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         true
     }
 
-    fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~[@u8]>();
-        if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; }
-        self.bump_past::<~[@u8]>();
-        true
-    }
-
     fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<&'static [u8]>();
         if ! self.inner.visit_evec_slice(mtbl, inner) { return false; }
index cc166b764d2c4388d3df7d4e46ed884037754031..7255448bd2395324bf08dea6fc90708e1f51f21d 100644 (file)
@@ -310,14 +310,6 @@ fn visit_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
         })
     }
 
-    fn visit_uniq_managed(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
-        self.writer.write(['~' as u8]);
-        self.get::<&raw::Box<()>>(|this, b| {
-            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
-            this.visit_ptr_inner(p, inner);
-        })
-    }
-
     fn visit_ptr(&mut self, mtbl: uint, _inner: *TyDesc) -> bool {
         self.get::<*c_void>(|this, p| {
             write!(this.writer, "({} as *", *p);
@@ -358,13 +350,6 @@ fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         })
     }
 
-    fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.get::<&raw::Box<raw::Vec<()>>>(|this, b| {
-            this.writer.write(['~' as u8]);
-            this.write_unboxed_vec_repr(mtbl, &b.data, inner);
-        })
-    }
-
     fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.get::<raw::Slice<()>>(|this, s| {
             this.writer.write(['&' as u8]);
index 16c1ad25448fc315897c680846a780631809442b..6ea12659e77f249b7767def0ea98db5e2a3014f5 100644 (file)
@@ -130,14 +130,14 @@ fn iter_crate_map_duplicates() {
         let child_crate = CrateMap {
             version: 2,
             entries: entries,
-            children: [],
+            children: &[],
             event_loop_factory: None,
         };
 
         let root_crate = CrateMap {
             version: 2,
-            entries: [],
-            children: [&child_crate, &child_crate],
+            entries: &[],
+            children: &[&child_crate, &child_crate],
             event_loop_factory: None,
         };
 
@@ -157,29 +157,29 @@ fn iter_crate_map_follow_children() {
         let mut level3: u32 = 3;
         let child_crate2 = CrateMap {
             version: 2,
-            entries: [
+            entries: &[
                 ModEntry { name: "c::m1", log_level: &mut level2},
                 ModEntry { name: "c::m2", log_level: &mut level3},
             ],
-            children: [],
+            children: &[],
             event_loop_factory: None,
         };
 
         let child_crate1 = CrateMap {
             version: 2,
-            entries: [
+            entries: &[
                 ModEntry { name: "t::f1", log_level: &mut 1},
             ],
-            children: [&child_crate2],
+            children: &[&child_crate2],
             event_loop_factory: None,
         };
 
         let root_crate = CrateMap {
             version: 2,
-            entries: [
+            entries: &[
                 ModEntry { name: "t::f2", log_level: &mut 0},
             ],
-            children: [&child_crate1],
+            children: &[&child_crate1],
             event_loop_factory: None,
         };
 
index 7a417990a4c1ac5dce234334bf552d819758f777..ce4072fb1ab924608272329504d2d5e108ebdc27 100644 (file)
 
 use libc::{c_void, c_char, size_t, uintptr_t, free, malloc, realloc};
 use ptr::RawPtr;
-use unstable::intrinsics::TyDesc;
+use unstable::intrinsics::{TyDesc, abort};
 use unstable::raw;
 use mem::size_of;
 
-extern {
-    fn abort();
-}
-
 #[inline]
 pub fn get_box_size(body_size: uint, body_align: uint) -> uint {
     let header_size = size_of::<raw::Box<()>>();
@@ -34,6 +30,7 @@ fn align_to(size: uint, align: uint) -> uint {
 }
 
 /// A wrapper around libc::malloc, aborting on out-of-memory
+#[inline]
 pub unsafe fn malloc_raw(size: uint) -> *c_void {
     let p = malloc(size as size_t);
     if p.is_null() {
@@ -44,6 +41,7 @@ pub unsafe fn malloc_raw(size: uint) -> *c_void {
 }
 
 /// A wrapper around libc::realloc, aborting on out-of-memory
+#[inline]
 pub unsafe fn realloc_raw(ptr: *mut c_void, size: uint) -> *mut c_void {
     let p = realloc(ptr, size as size_t);
     if p.is_null() {
@@ -94,6 +92,7 @@ pub unsafe fn exchange_free_(ptr: *c_char) {
     exchange_free(ptr)
 }
 
+#[inline]
 pub unsafe fn exchange_free(ptr: *c_char) {
     free(ptr as *c_void);
 }
index 1be942b2db19a9058a9d69cf2b5dd78ba14b4411..90179612272c2aa6df660bbdf580f9e7e66f7b4c 100644 (file)
@@ -48,6 +48,7 @@ pub struct LocalHeap {
 }
 
 impl LocalHeap {
+    #[inline]
     pub fn new() -> LocalHeap {
         let region = MemoryRegion {
             allocations: ~[],
@@ -60,6 +61,7 @@ pub fn new() -> LocalHeap {
         }
     }
 
+    #[inline]
     pub fn alloc(&mut self, td: *TyDesc, size: uint) -> *mut Box {
         let total_size = global_heap::get_box_size(size, unsafe { (*td).align });
         let alloc = self.memory_region.malloc(total_size);
@@ -80,6 +82,7 @@ pub fn alloc(&mut self, td: *TyDesc, size: uint) -> *mut Box {
         return alloc;
     }
 
+    #[inline]
     pub fn realloc(&mut self, ptr: *mut Box, size: uint) -> *mut Box {
         // Make sure that we can't use `mybox` outside of this scope
         let total_size = size + mem::size_of::<Box>();
@@ -100,6 +103,7 @@ pub fn realloc(&mut self, ptr: *mut Box, size: uint) -> *mut Box {
         return new_box;
     }
 
+    #[inline]
     pub fn free(&mut self, alloc: *mut Box) {
         {
             // Make sure that we can't use `mybox` outside of this scope
@@ -196,6 +200,7 @@ fn from(a_box: *mut Box) -> *mut AllocHeader {
 }
 
 impl MemoryRegion {
+    #[inline]
     fn malloc(&mut self, size: uint) -> *mut Box {
         let total_size = size + AllocHeader::size();
         let alloc: *AllocHeader = unsafe {
@@ -210,6 +215,7 @@ fn malloc(&mut self, size: uint) -> *mut Box {
         return alloc.as_box();
     }
 
+    #[inline]
     fn realloc(&mut self, alloc: *mut Box, size: uint) -> *mut Box {
         rtassert!(!alloc.is_null());
         let orig_alloc = AllocHeader::from(alloc);
@@ -228,6 +234,7 @@ fn realloc(&mut self, alloc: *mut Box, size: uint) -> *mut Box {
         return alloc.as_box();
     }
 
+    #[inline]
     fn free(&mut self, alloc: *mut Box) {
         rtassert!(!alloc.is_null());
         let alloc = AllocHeader::from(alloc);
@@ -249,6 +256,7 @@ fn claim(&mut self, alloc: &mut AllocHeader) {
         }
     }
     #[cfg(not(rtdebug))]
+    #[inline]
     fn claim(&mut self, _alloc: &mut AllocHeader) {}
 
     #[cfg(rtdebug)]
@@ -260,6 +268,7 @@ fn release(&mut self, alloc: &AllocHeader) {
         }
     }
     #[cfg(not(rtdebug))]
+    #[inline]
     fn release(&mut self, _alloc: &AllocHeader) {}
 
     #[cfg(rtdebug)]
@@ -271,6 +280,7 @@ fn update(&mut self, alloc: &mut AllocHeader, orig: *AllocHeader) {
         }
     }
     #[cfg(not(rtdebug))]
+    #[inline]
     fn update(&mut self, _alloc: &mut AllocHeader, _orig: *AllocHeader) {}
 }
 
@@ -283,6 +293,7 @@ fn drop(&mut self) {
     }
 }
 
+#[inline]
 pub unsafe fn local_malloc(td: *libc::c_char, size: libc::uintptr_t) -> *libc::c_char {
     // XXX: Unsafe borrow for speed. Lame.
     let task: Option<*mut Task> = Local::try_unsafe_borrow();
@@ -295,6 +306,7 @@ pub unsafe fn local_malloc(td: *libc::c_char, size: libc::uintptr_t) -> *libc::c
 }
 
 // A little compatibility function
+#[inline]
 pub unsafe fn local_free(ptr: *libc::c_char) {
     // XXX: Unsafe borrow for speed. Lame.
     let task_ptr: Option<*mut Task> = Local::try_unsafe_borrow();
index b4ead4252ca4158a461da8d94dea3b36a10f82bc..4df626446c4f0a9829720103d1ca65ccc5a3c7f4 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
 use task::{TaskResult, TaskOpts};
 use unstable::finally::Finally;
 
-// The Task struct represents all state associated with a rust
-// task. There are at this point two primary "subtypes" of task,
-// however instead of using a subtype we just have a "task_type" field
-// in the struct. This contains a pointer to another struct that holds
-// the type-specific state.
-
+/// The Task struct represents all state associated with a rust
+/// task. There are at this point two primary "subtypes" of task,
+/// however instead of using a subtype we just have a "task_type" field
+/// in the struct. This contains a pointer to another struct that holds
+/// the type-specific state.
 pub struct Task {
     heap: LocalHeap,
     gc: GarbageCollector,
index 3a07e8c373b754a035f3a136c215c0d5de34b44d..ffe254574eba3b29d122fa66d5b2e9f847953200 100644 (file)
@@ -364,6 +364,7 @@ pub extern "C" fn rust_eh_personality_catch(
 /// This is the entry point of unwinding for things like lang items and such.
 /// The arguments are normally generated by the compiler, and need to
 /// have static lifetimes.
+#[inline(never)] #[cold] // this is the slow path, please never inline this
 pub fn begin_unwind_raw(msg: *c_char, file: *c_char, line: size_t) -> ! {
     #[inline]
     fn static_char_ptr(p: *c_char) -> &'static str {
@@ -381,6 +382,7 @@ fn static_char_ptr(p: *c_char) -> &'static str {
 }
 
 /// This is the entry point of unwinding for fail!() and assert!().
+#[inline(never)] #[cold] // this is the slow path, please never inline this
 pub fn begin_unwind<M: Any + Send>(msg: M, file: &'static str, line: uint) -> ! {
     // Note that this should be the only allocation performed in this block.
     // Currently this means that fail!() on OOM will invoke this code path,
index ee336d7d847d5393b10ffaded77b3a1d4dd0896f..a5d5a4677f139c66cbee72e2ae2a4aa513e02b88 100644 (file)
@@ -141,6 +141,7 @@ pub fn abort(msg: &str) -> ! {
     abort();
 
     fn abort() -> ! {
-        unsafe { libc::abort() }
+        use std::unstable::intrinsics;
+        unsafe { intrinsics::abort() }
     }
 }
index d864cde2953ea1ad30760455cbce86f14a803d85..d8df84bbba8d1b88a90deabbdd5889758f60e7ce 100644 (file)
@@ -12,7 +12,7 @@
 
 use prelude::*;
 use uint;
-use util::{swap, replace};
+use util::replace;
 use vec;
 
 // FIXME: #5244: need to manually update the TrieNode constructor
@@ -415,39 +415,41 @@ fn find_mut<'r, T>(child: &'r mut Child<T>, key: uint, idx: uint) -> Option<&'r
 
 fn insert<T>(count: &mut uint, child: &mut Child<T>, key: uint, value: T,
              idx: uint) -> Option<T> {
-    let mut tmp = Nothing;
-    let ret;
-    swap(&mut tmp, child);
-
-    *child = match tmp {
-      External(stored_key, stored_value) => {
-          if stored_key == key {
-              ret = Some(stored_value);
-              External(stored_key, value)
-          } else {
-              // conflict - split the node
-              let mut new = ~TrieNode::new();
-              insert(&mut new.count,
-                     &mut new.children[chunk(stored_key, idx)],
-                     stored_key, stored_value, idx + 1);
-              ret = insert(&mut new.count, &mut new.children[chunk(key, idx)],
-                           key, value, idx + 1);
-              Internal(new)
-          }
-      }
-      Internal(x) => {
-        let mut x = x;
-        ret = insert(&mut x.count, &mut x.children[chunk(key, idx)], key,
-                     value, idx + 1);
-        Internal(x)
-      }
-      Nothing => {
-        *count += 1;
-        ret = None;
-        External(key, value)
-      }
-    };
-    return ret;
+    // we branch twice to avoid having to do the `replace` when we
+    // don't need to; this is much faster, especially for keys that
+    // have long shared prefixes.
+    match *child {
+        Nothing => {
+            *count += 1;
+            *child = External(key, value);
+            return None;
+        }
+        Internal(ref mut x) => {
+            return insert(&mut x.count, &mut x.children[chunk(key, idx)], key, value, idx + 1);
+        }
+        External(stored_key, ref mut stored_value) if stored_key == key => {
+            // swap in the new value and return the old.
+            return Some(replace(stored_value, value));
+        }
+        _ => {}
+    }
+
+    // conflict, an external node with differing keys: we have to
+    // split the node, so we need the old value by value; hence we
+    // have to move out of `child`.
+    match replace(child, Nothing) {
+        External(stored_key, stored_value) => {
+            let mut new = ~TrieNode::new();
+            insert(&mut new.count,
+                   &mut new.children[chunk(stored_key, idx)],
+                   stored_key, stored_value, idx + 1);
+            let ret = insert(&mut new.count, &mut new.children[chunk(key, idx)],
+                         key, value, idx + 1);
+            *child = Internal(new);
+            return ret;
+        }
+        _ => unreachable!()
+    }
 }
 
 fn remove<T>(count: &mut uint, child: &mut Child<T>, key: uint,
@@ -886,6 +888,54 @@ fn bench_upper_bound(bh: &mut BenchHarness) {
                 }
             });
     }
+
+    #[bench]
+    fn bench_insert_large(bh: &mut BenchHarness) {
+        let mut m = TrieMap::<[uint, .. 10]>::new();
+        let mut rng = weak_rng();
+
+        bh.iter(|| {
+                for _ in range(0, 1000) {
+                    m.insert(rng.gen(), [1, .. 10]);
+                }
+            })
+    }
+    #[bench]
+    fn bench_insert_large_low_bits(bh: &mut BenchHarness) {
+        let mut m = TrieMap::<[uint, .. 10]>::new();
+        let mut rng = weak_rng();
+
+        bh.iter(|| {
+                for _ in range(0, 1000) {
+                    // only have the last few bits set.
+                    m.insert(rng.gen::<uint>() & 0xff_ff, [1, .. 10]);
+                }
+            })
+    }
+
+    #[bench]
+    fn bench_insert_small(bh: &mut BenchHarness) {
+        let mut m = TrieMap::<()>::new();
+        let mut rng = weak_rng();
+
+        bh.iter(|| {
+                for _ in range(0, 1000) {
+                    m.insert(rng.gen(), ());
+                }
+            })
+    }
+    #[bench]
+    fn bench_insert_small_low_bits(bh: &mut BenchHarness) {
+        let mut m = TrieMap::<()>::new();
+        let mut rng = weak_rng();
+
+        bh.iter(|| {
+                for _ in range(0, 1000) {
+                    // only have the last few bits set.
+                    m.insert(rng.gen::<uint>() & 0xff_ff, ());
+                }
+            })
+    }
 }
 
 #[cfg(test)]
index acd1cfcf9013a9261afadba520be33f2d83e53af..198df3090ee80fcc39bc2a2df19eaf5b58120e5a 100644 (file)
 
 pub type GlueFn = extern "Rust" fn(*i8);
 
-// NOTE remove after next snapshot
 #[lang="ty_desc"]
-#[cfg(not(test), stage0)]
-pub struct TyDesc {
-    // sizeof(T)
-    size: uint,
-
-    // alignof(T)
-    align: uint,
-
-    // Called on a copy of a value of type `T` *after* memcpy
-    take_glue: GlueFn,
-
-    // Called when a value of type `T` is no longer needed
-    drop_glue: GlueFn,
-
-    // Called by drop glue when a value of type `T` can be freed
-    free_glue: GlueFn,
-
-    // Called by reflection visitor to visit a value of type `T`
-    visit_glue: GlueFn,
-
-    // If T represents a box pointer (`@U` or `~U`), then
-    // `borrow_offset` is the amount that the pointer must be adjusted
-    // to find the payload.  This is always derivable from the type
-    // `U`, but in the case of `@Trait` or `~Trait` objects, the type
-    // `U` is unknown.
-    borrow_offset: uint,
-
-    // Name corresponding to the type
-    name: &'static str
-}
-
-#[lang="ty_desc"]
-#[cfg(not(test), not(stage0))]
+#[cfg(not(test))]
 pub struct TyDesc {
     // sizeof(T)
     size: uint,
@@ -98,13 +65,6 @@ pub struct TyDesc {
     // Called by reflection visitor to visit a value of type `T`
     visit_glue: GlueFn,
 
-    // If T represents a box pointer (`@U` or `~U`), then
-    // `borrow_offset` is the amount that the pointer must be adjusted
-    // to find the payload.  This is always derivable from the type
-    // `U`, but in the case of `@Trait` or `~Trait` objects, the type
-    // `U` is unknown.
-    borrow_offset: uint,
-
     // Name corresponding to the type
     name: &'static str
 }
@@ -146,7 +106,6 @@ pub trait TyVisitor {
 
     fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
 
@@ -154,7 +113,6 @@ pub trait TyVisitor {
     fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
                         mtbl: uint, inner: *TyDesc) -> bool;
@@ -334,12 +292,6 @@ fn visit_leave_fn(&mut self, purity: uint, proto: uint,
     /// elements.
     pub fn size_of<T>() -> uint;
 
-    /// Move a value to a memory location containing a value.
-    ///
-    /// Drop glue is run on the destination, which must contain a
-    /// valid Rust value.
-    pub fn move_val<T>(dst: &mut T, src: T);
-
     /// Move a value to an uninitialized memory location.
     ///
     /// Drop glue is not run on the destination.
index e7e8cec9d5f178e8584969a8af511c3711eea91e..38c713ad7b7d7b308592d5d041e80eeb1460a5c9 100644 (file)
@@ -29,6 +29,7 @@ pub fn fail_bounds_check(file: *c_char, line: size_t, index: size_t, len: size_t
 }
 
 #[lang="malloc"]
+#[inline]
 pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
     ::rt::local_heap::local_malloc(td, size)
 }
@@ -37,6 +38,7 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
 // inside a landing pad may corrupt the state of the exception handler. If a
 // problem occurs, call exit instead.
 #[lang="free"]
+#[inline]
 pub unsafe fn local_free(ptr: *c_char) {
     ::rt::local_heap::local_free(ptr);
 }
index 64a9a7c672a90fddcbbb3a8aeacba8c9af02cf5d..8aee26c24b299a670b785278dae339f95a85361b 100644 (file)
@@ -57,6 +57,7 @@ impl<'a, T> Repr<Slice<T>> for &'a [T] {}
 impl<'a> Repr<Slice<u8>> for &'a str {}
 impl<T> Repr<*Box<T>> for @T {}
 impl<T> Repr<*Box<Vec<T>>> for @[T] {}
+impl<T> Repr<*Vec<T>> for ~[T] {}
 impl Repr<*String> for ~str {}
 impl Repr<*Box<String>> for @str {}
 
index 257a1e6340fa64a88b93de36ccfb337d8f210bc4..a7310bc75f193a2cb4d932a3ae1efd2bc68b1892 100644 (file)
 use ptr;
 use ptr::RawPtr;
 use rt::global_heap::{malloc_raw, realloc_raw, exchange_free};
-use rt::local_heap::local_free;
 use mem;
 use mem::size_of;
 use uint;
 use unstable::finally::Finally;
 use unstable::intrinsics;
-use unstable::intrinsics::{get_tydesc, owns_managed};
-use unstable::raw::{Box, Repr, Slice, Vec};
+use unstable::raw::{Repr, Slice, Vec};
 use util;
 
 /**
@@ -180,21 +178,15 @@ pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> ~[T] {
 #[inline]
 pub fn with_capacity<T>(capacity: uint) -> ~[T] {
     unsafe {
-        if owns_managed::<T>() {
-            let mut vec = ~[];
-            vec.reserve(capacity);
-            vec
-        } else {
-            let alloc = capacity * mem::nonzero_size_of::<T>();
-            let size = alloc + mem::size_of::<Vec<()>>();
-            if alloc / mem::nonzero_size_of::<T>() != capacity || size < alloc {
-                fail!("vector size is too large: {}", capacity);
-            }
-            let ptr = malloc_raw(size) as *mut Vec<()>;
-            (*ptr).alloc = alloc;
-            (*ptr).fill = 0;
-            cast::transmute(ptr)
+        let alloc = capacity * mem::nonzero_size_of::<T>();
+        let size = alloc + mem::size_of::<Vec<()>>();
+        if alloc / mem::nonzero_size_of::<T>() != capacity || size < alloc {
+            fail!("vector size is too large: {}", capacity);
         }
+        let ptr = malloc_raw(size) as *mut Vec<()>;
+        (*ptr).alloc = alloc;
+        (*ptr).fill = 0;
+        cast::transmute(ptr)
     }
 }
 
@@ -217,6 +209,25 @@ pub fn build<A>(size: Option<uint>, builder: |push: |v: A||) -> ~[A] {
     vec
 }
 
+/**
+ * Converts a pointer to A into a slice of length 1 (without copying).
+ */
+pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
+    unsafe {
+        cast::transmute(Slice { data: s, len: 1 })
+    }
+}
+
+/**
+ * Converts a pointer to A into a slice of length 1 (without copying).
+ */
+pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
+    unsafe {
+        let ptr: *A = cast::transmute(s);
+        cast::transmute(Slice { data: ptr, len: 1 })
+    }
+}
+
 /// An iterator over the slices of a vector separated by elements that
 /// match a predicate function.
 pub struct SplitIterator<'a, T> {
@@ -784,7 +795,7 @@ impl<T> Container for ~[T] {
     /// Returns the length of a vector
     #[inline]
     fn len(&self) -> uint {
-        self.repr().len
+        self.as_slice().len()
     }
 }
 
@@ -1485,21 +1496,15 @@ fn reserve(&mut self, n: uint) {
         // Only make the (slow) call into the runtime if we have to
         if self.capacity() < n {
             unsafe {
-                let td = get_tydesc::<T>();
-                if owns_managed::<T>() {
-                    let ptr: *mut *mut Box<Vec<()>> = cast::transmute(self);
-                    ::at_vec::raw::reserve_raw(td, ptr, n);
-                } else {
-                    let ptr: *mut *mut Vec<()> = cast::transmute(self);
-                    let alloc = n * mem::nonzero_size_of::<T>();
-                    let size = alloc + mem::size_of::<Vec<()>>();
-                    if alloc / mem::nonzero_size_of::<T>() != n || size < alloc {
-                        fail!("vector size is too large: {}", n);
-                    }
-                    *ptr = realloc_raw(*ptr as *mut c_void, size)
-                           as *mut Vec<()>;
-                    (**ptr).alloc = alloc;
+                let ptr: *mut *mut Vec<()> = cast::transmute(self);
+                let alloc = n * mem::nonzero_size_of::<T>();
+                let size = alloc + mem::size_of::<Vec<()>>();
+                if alloc / mem::nonzero_size_of::<T>() != n || size < alloc {
+                    fail!("vector size is too large: {}", n);
                 }
+                *ptr = realloc_raw(*ptr as *mut c_void, size)
+                       as *mut Vec<()>;
+                (**ptr).alloc = alloc;
             }
         }
     }
@@ -1522,13 +1527,8 @@ fn reserve_additional(&mut self, n: uint) {
     #[inline]
     fn capacity(&self) -> uint {
         unsafe {
-            if owns_managed::<T>() {
-                let repr: **Box<Vec<()>> = cast::transmute(self);
-                (**repr).data.alloc / mem::nonzero_size_of::<T>()
-            } else {
-                let repr: **Vec<()> = cast::transmute(self);
-                (**repr).alloc / mem::nonzero_size_of::<T>()
-            }
+            let repr: **Vec<()> = cast::transmute(self);
+            (**repr).alloc / mem::nonzero_size_of::<T>()
         }
     }
 
@@ -1545,45 +1545,25 @@ fn shrink_to_fit(&mut self) {
     #[inline]
     fn push(&mut self, t: T) {
         unsafe {
-            if owns_managed::<T>() {
-                let repr: **Box<Vec<()>> = cast::transmute(&mut *self);
-                let fill = (**repr).data.fill;
-                if (**repr).data.alloc <= fill {
-                    self.reserve_additional(1);
-                }
-
-                push_fast(self, t);
-            } else {
-                let repr: **Vec<()> = cast::transmute(&mut *self);
-                let fill = (**repr).fill;
-                if (**repr).alloc <= fill {
-                    self.reserve_additional(1);
-                }
-
-                push_fast(self, t);
+            let repr: **Vec<()> = cast::transmute(&mut *self);
+            let fill = (**repr).fill;
+            if (**repr).alloc <= fill {
+                self.reserve_additional(1);
             }
+
+            push_fast(self, t);
         }
 
         // This doesn't bother to make sure we have space.
         #[inline] // really pretty please
         unsafe fn push_fast<T>(this: &mut ~[T], t: T) {
-            if owns_managed::<T>() {
-                let repr: **mut Box<Vec<u8>> = cast::transmute(this);
-                let fill = (**repr).data.fill;
-                (**repr).data.fill += mem::nonzero_size_of::<T>();
-                let p = to_unsafe_ptr(&((**repr).data.data));
-                let p = ptr::offset(p, fill as int) as *mut T;
-                intrinsics::move_val_init(&mut(*p), t);
-            } else {
-                let repr: **mut Vec<u8> = cast::transmute(this);
-                let fill = (**repr).fill;
-                (**repr).fill += mem::nonzero_size_of::<T>();
-                let p = to_unsafe_ptr(&((**repr).data));
-                let p = ptr::offset(p, fill as int) as *mut T;
-                intrinsics::move_val_init(&mut(*p), t);
-            }
+            let repr: **mut Vec<u8> = cast::transmute(this);
+            let fill = (**repr).fill;
+            (**repr).fill += mem::nonzero_size_of::<T>();
+            let p = to_unsafe_ptr(&((**repr).data));
+            let p = ptr::offset(p, fill as int) as *mut T;
+            intrinsics::move_val_init(&mut(*p), t);
         }
-
     }
 
     #[inline]
@@ -1745,15 +1725,11 @@ fn grow_fn(&mut self, n: uint, op: |uint| -> T) {
             i += 1u;
         }
     }
+
     #[inline]
     unsafe fn set_len(&mut self, new_len: uint) {
-        if owns_managed::<T>() {
-            let repr: **mut Box<Vec<()>> = cast::transmute(self);
-            (**repr).data.fill = new_len * mem::nonzero_size_of::<T>();
-        } else {
-            let repr: **mut Vec<()> = cast::transmute(self);
-            (**repr).fill = new_len * mem::nonzero_size_of::<T>();
-        }
+        let repr: **mut Vec<()> = cast::transmute(self);
+        (**repr).fill = new_len * mem::nonzero_size_of::<T>();
     }
 }
 
@@ -1837,11 +1813,8 @@ impl<T:Eq> OwnedEqVector<T> for ~[T] {
     fn dedup(&mut self) {
         unsafe {
             // Although we have a mutable reference to `self`, we cannot make
-            // *arbitrary* changes. There exists the possibility that this
-            // vector is contained with an `@mut` box and hence is still
-            // readable by the outside world during the `Eq` comparisons.
-            // Moreover, those comparisons could fail, so we must ensure
-            // that the vector is in a valid state at all time.
+            // *arbitrary* changes. The `Eq` comparisons could fail, so we
+            // must ensure that the vector is in a valid state at all time.
             //
             // The way that we handle this is by using swaps; we iterate
             // over all the elements, swapping as we go so that at the end
@@ -2094,6 +2067,9 @@ pub trait MutableVector<'a, T> {
     /// Returns an iterator that allows modifying each value
     fn mut_iter(self) -> VecMutIterator<'a, T>;
 
+    /// Returns a mutable pointer to the last item in the vector.
+    fn mut_last(self) -> &'a mut T;
+
     /// Returns a reversed iterator that allows modifying each value
     fn mut_rev_iter(self) -> MutRevIterator<'a, T>;
 
@@ -2356,6 +2332,13 @@ fn mut_iter(self) -> VecMutIterator<'a, T> {
         }
     }
 
+    #[inline]
+    fn mut_last(self) -> &'a mut T {
+        let len = self.len();
+        if len == 0 { fail!("mut_last: empty vector") }
+        &mut self[len - 1]
+    }
+
     #[inline]
     fn mut_rev_iter(self) -> MutRevIterator<'a, T> {
         self.mut_iter().invert()
@@ -2934,11 +2917,7 @@ fn drop(&mut self) {
         // destroy the remaining elements
         for _x in *self {}
         unsafe {
-            if owns_managed::<T>() {
-                local_free(self.allocation as *u8 as *c_char)
-            } else {
-                exchange_free(self.allocation as *u8 as *c_char)
-            }
+            exchange_free(self.allocation as *u8 as *c_char)
         }
     }
 }
index ab16ab153d9c06ff1a674d42fdf52628d893386b..800172daf1500b7dfa39a6d1290a075b59c01335 100644 (file)
@@ -638,13 +638,6 @@ pub enum TokenTree {
     TTNonterminal(Span, Ident)
 }
 
-// NOTE remove after next snapshot
-// Required for ext::quote macros.
-#[cfg(stage0)]
-pub fn tt_tok(span: Span, tok: ::parse::token::Token) -> TokenTree {
-    TTTok(span, tok)
-}
-
 //
 // Matchers are nodes defined-by and recognized-by the main rust parser and
 // language, but they're only ever found inside syntax-extension invocations;
@@ -959,10 +952,10 @@ pub enum RetStyle {
 #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum ExplicitSelf_ {
     SelfStatic,                                // no self
-    SelfValue(Mutability),                     // `self`
-    SelfRegion(Option<Lifetime>, Mutability),  // `&'lt self`
-    SelfBox(Mutability),                       // `@self`
-    SelfUniq(Mutability)                       // `~self`
+    SelfValue(Mutability),                     // `self`, `mut self`
+    SelfRegion(Option<Lifetime>, Mutability),  // `&'lt self`, `&'lt mut self`
+    SelfBox,                                   // `@self`
+    SelfUniq(Mutability)                       // `~self`, `mut ~self`
 }
 
 pub type ExplicitSelf = Spanned<ExplicitSelf_>;
@@ -1202,123 +1195,32 @@ pub enum InlinedItem {
 
 #[cfg(test)]
 mod test {
+    use extra;
+    use codemap::*;
     use super::*;
 
     fn is_freeze<T: Freeze>() {}
 
     // Assert that the AST remains Freeze (#10693).
-    #[test] fn ast_is_freeze() {
+    #[test]
+    fn ast_is_freeze() {
         is_freeze::<Item>();
     }
-}
-
-/* hold off on tests ... they appear in a later merge.
-#[cfg(test)]
-mod test {
-    use std::option::{None, Option, Some};
-    use std::uint;
-    use extra;
-    use codemap::*;
-    use super::*;
-
-
-    #[test] fn xorpush_test () {
-        let mut s = ~[];
-        xorPush(&mut s,14);
-        assert_eq!(s,~[14]);
-        xorPush(&mut s,14);
-        assert_eq!(s,~[]);
-        xorPush(&mut s,14);
-        assert_eq!(s,~[14]);
-        xorPush(&mut s,15);
-        assert_eq!(s,~[14,15]);
-        xorPush (&mut s,16);
-        assert_eq! (s,~[14,15,16]);
-        xorPush (&mut s,16);
-        assert_eq! (s,~[14,15]);
-        xorPush (&mut s,15);
-        assert_eq! (s,~[14]);
-    }
-
-    #[test] fn test_marksof () {
-        let stopname = uints_to_name(&~[12,14,78]);
-        assert_eq!(s,~[]);
-        xorPush(&mut s,14);
-        assert_eq!(s,~[14]);
-        xorPush(&mut s,15);
-        assert_eq!(s,~[14,15]);
-        xorPush (&mut s,16);
-        assert_eq! (s,~[14,15,16]);
-        xorPush (&mut s,16);
-        assert_eq! (s,~[14,15]);
-        xorPush (&mut s,15);
-        assert_eq! (s,~[14]);
-    }
-
-    #[test] fn test_marksof () {
-        let stopname = uints_to_name(&~[12,14,78]);
-        let name1 = uints_to_name(&~[4,9,7]);
-        assert_eq!(marksof (MT,stopname),~[]);
-        assert_eq! (marksof (Mark (4,@Mark(98,@MT)),stopname),~[4,98]);
-        // does xoring work?
-        assert_eq! (marksof (Mark (5, @Mark (5, @Mark (16,@MT))),stopname),
-                     ~[16]);
-        // does nested xoring work?
-        assert_eq! (marksof (Mark (5,
-                                    @Mark (10,
-                                           @Mark (10,
-                                                  @Mark (5,
-                                                         @Mark (16,@MT))))),
-                              stopname),
-                     ~[16]);
-        // stop has no effect on marks
-        assert_eq! (marksof (Mark (9, @Mark (14, @Mark (12, @MT))),stopname),
-                     ~[9,14,12]);
-        // rename where stop doesn't match:
-        assert_eq! (marksof (Mark (9, @Rename
-                                    (name1,
-                                     @Mark (4, @MT),
-                                     uints_to_name(&~[100,101,102]),
-                                     @Mark (14, @MT))),
-                              stopname),
-                     ~[9,14]);
-        // rename where stop does match
-        ;
-        assert_eq! (marksof (Mark(9, @Rename (name1,
-                                               @Mark (4, @MT),
-                                               stopname,
-                                               @Mark (14, @MT))),
-                              stopname),
-                     ~[9]);
-    }
 
     // are ASTs encodable?
-    #[test] fn check_asts_encodable() {
-        let bogus_span = span {lo:BytePos(10),
-                               hi:BytePos(20),
-                               expn_info:None};
-        let e : crate =
-            spanned{
-            node: crate_{
-                module: Mod {view_items: ~[], items: ~[]},
-                attrs: ~[],
-                config: ~[]
+    #[test]
+    fn check_asts_encodable() {
+        let e = Crate {
+            module: Mod {view_items: ~[], items: ~[]},
+            attrs: ~[],
+            config: ~[],
+            span: Span {
+                lo: BytePos(10),
+                hi: BytePos(20),
+                expn_info: None,
             },
-            span: bogus_span};
+        };
         // doesn't matter which encoder we use....
         let _f = (@e as @extra::serialize::Encodable<extra::json::Encoder>);
     }
-
-
 }
-
-*/
-//
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
index 3e0caab65c24096dce0ecec407170fd7e0d5e319..598e30957e4f2a409be619fabf1504b5eef66312 100644 (file)
@@ -567,11 +567,7 @@ pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
         visited_outermost: false,
     };
 
-    match *item {
-        IIItem(i) => id_visitor.visit_item(i, ()),
-        IIForeign(i) => id_visitor.visit_foreign_item(i, ()),
-        IIMethod(_, _, m) => visit::walk_method_helper(&mut id_visitor, m, ()),
-    }
+    visit::walk_inlined_item(&mut id_visitor, item, ());
 }
 
 struct IdRangeComputingVisitor {
@@ -872,9 +868,11 @@ pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] {
             table.get()[loopvar]
         };
         match table_entry {
-            EmptyCtxt => {return result;},
-            Mark(mark,tl) => {
-                xorPush(&mut result,mark);
+            EmptyCtxt => {
+                return result;
+            },
+            Mark(mark, tl) => {
+                xorPush(&mut result, mark);
                 loopvar = tl;
             },
             Rename(_,name,tl) => {
@@ -980,20 +978,20 @@ fn ident_to_segment(id : &Ident) -> PathSegment {
 
     #[test] fn xorpush_test () {
         let mut s = ~[];
-        xorPush(&mut s,14);
-        assert_eq!(s.clone(),~[14]);
-        xorPush(&mut s,14);
-        assert_eq!(s.clone(),~[]);
-        xorPush(&mut s,14);
-        assert_eq!(s.clone(),~[14]);
-        xorPush(&mut s,15);
-        assert_eq!(s.clone(),~[14,15]);
-        xorPush (&mut s,16);
-        assert_eq!(s.clone(),~[14,15,16]);
-        xorPush (&mut s,16);
-        assert_eq!(s.clone(),~[14,15]);
-        xorPush (&mut s,15);
-        assert_eq!(s.clone(),~[14]);
+        xorPush(&mut s, 14);
+        assert_eq!(s.clone(), ~[14]);
+        xorPush(&mut s, 14);
+        assert_eq!(s.clone(), ~[]);
+        xorPush(&mut s, 14);
+        assert_eq!(s.clone(), ~[14]);
+        xorPush(&mut s, 15);
+        assert_eq!(s.clone(), ~[14, 15]);
+        xorPush(&mut s, 16);
+        assert_eq!(s.clone(), ~[14, 15, 16]);
+        xorPush(&mut s, 16);
+        assert_eq!(s.clone(), ~[14, 15]);
+        xorPush(&mut s, 15);
+        assert_eq!(s.clone(), ~[14]);
     }
 
     fn id(n: Name, s: SyntaxContext) -> Ident {
index 8f5c4904c782bfd98a87d06540aeb41b030eb916..904ef91d635713cb68f7e5c7a26efeeca1f9e7d0 100644 (file)
@@ -191,15 +191,6 @@ pub struct FileLines
     lines: ~[uint]
 }
 
-// represents the origin of a file:
-pub enum FileSubstr {
-    // indicates that this is a normal standalone file:
-    FssNone,
-    // indicates that this "file" is actually a substring
-    // of another file that appears earlier in the codemap
-    FssInternal(Span),
-}
-
 /// Identifies an offset of a multi-byte character in a FileMap
 pub struct MultiByteChar {
     /// The absolute offset of the character in the CodeMap
@@ -214,8 +205,6 @@ pub struct FileMap {
     /// originate from files has names between angle brackets by convention,
     /// e.g. `<anon>`
     name: FileName,
-    /// Extra information used by qquote
-    substr: FileSubstr,
     /// The complete source code
     src: @str,
     /// The start position of this source in the CodeMap
@@ -278,16 +267,7 @@ pub fn new() -> CodeMap {
         }
     }
 
-    /// Add a new FileMap to the CodeMap and return it
     pub fn new_filemap(&self, filename: FileName, src: @str) -> @FileMap {
-        return self.new_filemap_w_substr(filename, FssNone, src);
-    }
-
-    pub fn new_filemap_w_substr(&self,
-                                filename: FileName,
-                                substr: FileSubstr,
-                                src: @str)
-                                -> @FileMap {
         let mut files = self.files.borrow_mut();
         let start_pos = if files.get().len() == 0 {
             0
@@ -298,7 +278,8 @@ pub fn new_filemap_w_substr(&self,
         };
 
         let filemap = @FileMap {
-            name: filename, substr: substr, src: src,
+            name: filename,
+            src: src,
             start_pos: Pos::from_uint(start_pos),
             lines: RefCell::new(~[]),
             multibyte_chars: RefCell::new(~[]),
@@ -322,31 +303,16 @@ pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
 
     pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt {
         let loc = self.lookup_char_pos(pos);
-        match (loc.file.substr) {
-            FssNone =>
-            LocWithOpt {
-                filename: loc.file.name,
-                line: loc.line,
-                col: loc.col,
-                file: Some(loc.file)},
-            FssInternal(sp) =>
-            self.lookup_char_pos_adj(
-                sp.lo + (pos - loc.file.start_pos)),
+        LocWithOpt {
+            filename: loc.file.name,
+            line: loc.line,
+            col: loc.col,
+            file: Some(loc.file)
         }
     }
 
     pub fn adjust_span(&self, sp: Span) -> Span {
-        let line = self.lookup_line(sp.lo);
-        match (line.fm.substr) {
-            FssNone => sp,
-            FssInternal(s) => {
-                self.adjust_span(Span {
-                    lo: s.lo + (sp.lo - line.fm.start_pos),
-                    hi: s.lo + (sp.hi - line.fm.start_pos),
-                    expn_info: sp.expn_info
-                })
-            }
-        }
+        sp
     }
 
     pub fn span_to_str(&self, sp: Span) -> ~str {
index 8515c3aba50194bdbdef7e388a1cc7f4fefb9460..ef6d154c651a3655d8eb06de161dc59046fd73c4 100644 (file)
@@ -20,6 +20,7 @@
 use util::small_vector::SmallVector;
 
 use std::hashmap::HashMap;
+use std::unstable::dynamic_lib::DynamicLibrary;
 
 // new-style macro! tt code:
 //
@@ -120,6 +121,9 @@ fn expand(&self,
 pub type SyntaxExpanderTTItemFunNoCtxt =
     fn(&mut ExtCtxt, Span, ast::Ident, ~[ast::TokenTree]) -> MacResult;
 
+pub type MacroCrateRegistrationFun =
+    extern "Rust" fn(|ast::Name, SyntaxExtension|);
+
 pub trait AnyMacro {
     fn make_expr(&self) -> @ast::Expr;
     fn make_items(&self) -> SmallVector<@ast::Item>;
@@ -151,24 +155,21 @@ pub enum SyntaxExtension {
     IdentTT(~SyntaxExpanderTTItemTrait:'static, Option<Span>),
 }
 
-
-// The SyntaxEnv is the environment that's threaded through the expansion
-// of macros. It contains bindings for macros, and also a special binding
-// for " block" (not a legal identifier) that maps to a BlockInfo
-pub type SyntaxEnv = MapChain<Name, SyntaxExtension>;
-
 pub struct BlockInfo {
     // should macros escape from this scope?
     macros_escape : bool,
     // what are the pending renames?
-    pending_renames : RenameList
+    pending_renames : RenameList,
+    // references for crates loaded in this scope
+    macro_crates: ~[DynamicLibrary],
 }
 
 impl BlockInfo {
     pub fn new() -> BlockInfo {
         BlockInfo {
             macros_escape: false,
-            pending_renames: ~[]
+            pending_renames: ~[],
+            macro_crates: ~[],
         }
     }
 }
@@ -189,7 +190,7 @@ fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt)
         None)
     }
 
-    let mut syntax_expanders = MapChain::new();
+    let mut syntax_expanders = SyntaxEnv::new();
     syntax_expanders.insert(intern(&"macro_rules"),
                             IdentTT(~SyntaxExpanderTTItem {
                                 expander: SyntaxExpanderTTItemExpanderWithContext(
@@ -280,25 +281,38 @@ fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt)
     syntax_expanders
 }
 
+pub struct MacroCrate {
+    lib: Option<Path>,
+    cnum: ast::CrateNum,
+}
+
+pub trait CrateLoader {
+    fn load_crate(&mut self, crate: &ast::ViewItem) -> MacroCrate;
+    fn get_exported_macros(&mut self, crate_num: ast::CrateNum) -> ~[@ast::Item];
+    fn get_registrar_symbol(&mut self, crate_num: ast::CrateNum) -> Option<~str>;
+}
+
 // One of these is made during expansion and incrementally updated as we go;
 // when a macro expansion occurs, the resulting nodes have the backtrace()
 // -> expn_info of their expansion context stored into their span.
-pub struct ExtCtxt {
+pub struct ExtCtxt<'a> {
     parse_sess: @parse::ParseSess,
     cfg: ast::CrateConfig,
     backtrace: Option<@ExpnInfo>,
+    loader: &'a mut CrateLoader,
 
     mod_path: ~[ast::Ident],
     trace_mac: bool
 }
 
-impl ExtCtxt {
-    pub fn new(parse_sess: @parse::ParseSess, cfg: ast::CrateConfig)
-               -> ExtCtxt {
+impl<'a> ExtCtxt<'a> {
+    pub fn new<'a>(parse_sess: @parse::ParseSess, cfg: ast::CrateConfig,
+               loader: &'a mut CrateLoader) -> ExtCtxt<'a> {
         ExtCtxt {
             parse_sess: parse_sess,
             cfg: cfg,
             backtrace: None,
+            loader: loader,
             mod_path: ~[],
             trace_mac: false
         }
@@ -456,20 +470,27 @@ pub fn get_exprs_from_tts(cx: &ExtCtxt,
 // able to refer to a macro that was added to an enclosing
 // scope lexically later than the deeper scope.
 
-// Only generic to make it easy to test
-struct MapChainFrame<K, V> {
+struct MapChainFrame {
     info: BlockInfo,
-    map: HashMap<K, V>,
+    map: HashMap<Name, SyntaxExtension>,
+}
+
+#[unsafe_destructor]
+impl Drop for MapChainFrame {
+    fn drop(&mut self) {
+        // make sure that syntax extension dtors run before we drop the libs
+        self.map.clear();
+    }
 }
 
 // Only generic to make it easy to test
-pub struct MapChain<K, V> {
-    priv chain: ~[MapChainFrame<K, V>],
+pub struct SyntaxEnv {
+    priv chain: ~[MapChainFrame],
 }
 
-impl<K: Hash+Eq, V> MapChain<K, V> {
-    pub fn new() -> MapChain<K, V> {
-        let mut map = MapChain { chain: ~[] };
+impl SyntaxEnv {
+    pub fn new() -> SyntaxEnv {
+        let mut map = SyntaxEnv { chain: ~[] };
         map.push_frame();
         map
     }
@@ -486,7 +507,7 @@ pub fn pop_frame(&mut self) {
         self.chain.pop();
     }
 
-    fn find_escape_frame<'a>(&'a mut self) -> &'a mut MapChainFrame<K, V> {
+    fn find_escape_frame<'a>(&'a mut self) -> &'a mut MapChainFrame {
         for (i, frame) in self.chain.mut_iter().enumerate().invert() {
             if !frame.info.macros_escape || i == 0 {
                 return frame
@@ -495,7 +516,7 @@ fn find_escape_frame<'a>(&'a mut self) -> &'a mut MapChainFrame<K, V> {
         unreachable!()
     }
 
-    pub fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
+    pub fn find<'a>(&'a self, k: &Name) -> Option<&'a SyntaxExtension> {
         for frame in self.chain.iter().invert() {
             match frame.map.find(k) {
                 Some(v) => return Some(v),
@@ -505,49 +526,15 @@ pub fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
         None
     }
 
-    pub fn insert(&mut self, k: K, v: V) {
+    pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
         self.find_escape_frame().map.insert(k, v);
     }
 
-    pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {
-        &mut self.chain[self.chain.len()-1].info
+    pub fn insert_macro_crate(&mut self, lib: DynamicLibrary) {
+        self.find_escape_frame().info.macro_crates.push(lib);
     }
-}
 
-#[cfg(test)]
-mod test {
-    use super::MapChain;
-
-    #[test]
-    fn testenv() {
-        let mut m = MapChain::new();
-        let (a,b,c,d) = ("a", "b", "c", "d");
-        m.insert(1, a);
-        assert_eq!(Some(&a), m.find(&1));
-
-        m.push_frame();
-        m.info().macros_escape = true;
-        m.insert(2, b);
-        assert_eq!(Some(&a), m.find(&1));
-        assert_eq!(Some(&b), m.find(&2));
-        m.pop_frame();
-
-        assert_eq!(Some(&a), m.find(&1));
-        assert_eq!(Some(&b), m.find(&2));
-
-        m.push_frame();
-        m.push_frame();
-        m.info().macros_escape = true;
-        m.insert(3, c);
-        assert_eq!(Some(&c), m.find(&3));
-        m.pop_frame();
-        assert_eq!(Some(&c), m.find(&3));
-        m.pop_frame();
-        assert_eq!(None, m.find(&3));
-
-        m.push_frame();
-        m.insert(4, d);
-        m.pop_frame();
-        assert_eq!(None, m.find(&4));
+    pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {
+        &mut self.chain[self.chain.len()-1].info
     }
 }
index 85cda0bd1ae83d363b9ca9411305da93989f72e4..d702ee3ead4f6553a165114c7453b3bba6e92fe6 100644 (file)
@@ -236,7 +236,7 @@ fn view_use_glob(&self, sp: Span,
                      vis: ast::Visibility, path: ~[ast::Ident]) -> ast::ViewItem;
 }
 
-impl AstBuilder for ExtCtxt {
+impl<'a> AstBuilder for ExtCtxt<'a> {
     fn path(&self, span: Span, strs: ~[ast::Ident]) -> ast::Path {
         self.path_all(span, false, strs, opt_vec::Empty, ~[])
     }
@@ -896,7 +896,7 @@ fn view_use_glob(&self, sp: Span,
 }
 
 struct Duplicator<'a> {
-    cx: &'a ExtCtxt,
+    cx: &'a ExtCtxt<'a>,
 }
 
 impl<'a> Folder for Duplicator<'a> {
index 826d5381d4743c9d5a00f4186168a3db023f3385..202746acddce1a01b604ed2a03835f1a2e1b3502 100644 (file)
@@ -190,7 +190,7 @@ fn eq(&self, other: &int) -> bool {
 
 pub struct TraitDef<'a> {
     /// The extension context
-    cx: &'a ExtCtxt,
+    cx: &'a ExtCtxt<'a>,
     /// The span for the current #[deriving(Foo)] header.
     span: Span,
 
index a2e69cd377a3588cbb128f9737a93948680b1dd2..c2b32b45ce45b2f4d6a0d5216cf187816ed5a3a7 100644 (file)
@@ -251,7 +251,7 @@ pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
                 span,
                 match *ptr {
                     Send => ast::SelfUniq(ast::MutImmutable),
-                    Managed => ast::SelfBox(ast::MutImmutable),
+                    Managed => ast::SelfBox,
                     Borrowed(ref lt, mutbl) => {
                         let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s)));
                         ast::SelfRegion(lt, mutbl)
index 303277afbe84f94dccd99ded144c26188b2df786..7d46f6e459450c20eb6eb1161a8c0c8c7ac605b5 100644 (file)
@@ -30,6 +30,7 @@
 use util::small_vector::SmallVector;
 
 use std::vec;
+use std::unstable::dynamic_lib::DynamicLibrary;
 
 pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
     match e.node {
@@ -137,15 +138,16 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
 
             // to:
             //
-            // {
-            //   let _i = &mut <src_expr>;
-            //   ['<ident>:] loop {
-            //       match i.next() {
+            //   match &mut <src_expr> {
+            //     i => {
+            //       ['<ident>:] loop {
+            //         match i.next() {
             //           None => break,
             //           Some(<src_pat>) => <src_loop_block>
+            //         }
             //       }
+            //     }
             //   }
-            // }
 
             let local_ident = token::gensym_ident("i");
             let next_ident = fld.cx.ident_of("next");
@@ -154,10 +156,6 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
             let local_path = fld.cx.path_ident(span, local_ident);
             let some_path = fld.cx.path_ident(span, fld.cx.ident_of("Some"));
 
-            // `let i = &mut <src_expr>`
-            let iter_decl_stmt = fld.cx.stmt_let(span, false, local_ident,
-                                                 fld.cx.expr_mut_addr_of(span, src_expr));
-
             // `None => break ['<ident>];`
             let none_arm = {
                 // FIXME #6993: this map goes away:
@@ -185,16 +183,13 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
                                         ast::ExprLoop(fld.cx.block_expr(match_expr),
                                                       opt_ident));
 
-            // `{ let ... ;  loop { ... } }`
-            let block = fld.cx.block(span,
-                                     ~[iter_decl_stmt],
-                                     Some(loop_expr));
+            // `i => loop { ... }`
 
-            @ast::Expr {
-                id: ast::DUMMY_NODE_ID,
-                node: ast::ExprBlock(block),
-                span: span,
-            }
+            // `match &mut <src_expr> { i => loop { ... } }`
+            let discrim = fld.cx.expr_mut_addr_of(span, src_expr);
+            let i_pattern = fld.cx.pat_ident(span, local_ident);
+            let arm = fld.cx.arm(span, ~[i_pattern], loop_expr);
+            fld.cx.expr_match(span, discrim, ~[arm])
         }
 
         _ => noop_fold_expr(e, fld)
@@ -365,13 +360,79 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
             // yikes... no idea how to apply the mark to this. I'm afraid
             // we're going to have to wait-and-see on this one.
             fld.extsbox.insert(intern(name), ext);
-            SmallVector::zero()
+            if attr::contains_name(it.attrs, "macro_export") {
+                SmallVector::one(it)
+            } else {
+                SmallVector::zero()
+            }
         }
     };
     fld.cx.bt_pop();
     return items;
 }
 
+// load macros from syntax-phase crates
+pub fn expand_view_item(vi: &ast::ViewItem,
+                        fld: &mut MacroExpander)
+                        -> ast::ViewItem {
+    let should_load = vi.attrs.iter().any(|attr| {
+        "phase" == attr.name() &&
+            attr.meta_item_list().map_or(false, |phases| {
+                attr::contains_name(phases, "syntax")
+            })
+    });
+
+    if should_load {
+        load_extern_macros(vi, fld);
+    }
+
+    noop_fold_view_item(vi, fld)
+}
+
+fn load_extern_macros(crate: &ast::ViewItem, fld: &mut MacroExpander) {
+    let MacroCrate { lib, cnum } = fld.cx.loader.load_crate(crate);
+
+    let exported_macros = fld.cx.loader.get_exported_macros(cnum);
+    for &it in exported_macros.iter() {
+        expand_item_mac(it, fld);
+    }
+
+    let path = match lib {
+        Some(path) => path,
+        None => return
+    };
+    // Make sure the path contains a / or the linker will search for it.
+    // If path is already absolute this is a no-op.
+    let path = Path::new(".").join(path);
+
+    let registrar = match fld.cx.loader.get_registrar_symbol(cnum) {
+        Some(registrar) => registrar,
+        None => return
+    };
+
+    let lib = match DynamicLibrary::open(Some(&path)) {
+        Ok(lib) => lib,
+        Err(err) => fld.cx.span_fatal(crate.span, err)
+    };
+
+    unsafe {
+        let registrar: MacroCrateRegistrationFun = match lib.symbol(registrar) {
+            Ok(registrar) => registrar,
+            Err(err) => fld.cx.span_fatal(crate.span, err)
+        };
+        registrar(|name, extension| {
+            let extension = match extension {
+                NormalTT(ext, _) => NormalTT(ext, Some(crate.span)),
+                IdentTT(ext, _) => IdentTT(ext, Some(crate.span)),
+                ItemDecorator(ext) => ItemDecorator(ext),
+            };
+            fld.extsbox.insert(name, extension);
+        });
+    }
+
+    fld.extsbox.insert_macro_crate(lib);
+}
+
 // expand a stmt
 pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
     // why the copying here and not in expand_expr?
@@ -878,7 +939,7 @@ pub fn inject_std_macros(parse_sess: @parse::ParseSess,
 
 pub struct MacroExpander<'a> {
     extsbox: SyntaxEnv,
-    cx: &'a mut ExtCtxt,
+    cx: &'a mut ExtCtxt<'a>,
 }
 
 impl<'a> Folder for MacroExpander<'a> {
@@ -894,6 +955,10 @@ fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> {
         expand_item(item, self)
     }
 
+    fn fold_view_item(&mut self, vi: &ast::ViewItem) -> ast::ViewItem {
+        expand_view_item(vi, self)
+    }
+
     fn fold_stmt(&mut self, stmt: &ast::Stmt) -> SmallVector<@ast::Stmt> {
         expand_stmt(stmt, self)
     }
@@ -908,9 +973,10 @@ fn new_span(&mut self, span: Span) -> Span {
 }
 
 pub fn expand_crate(parse_sess: @parse::ParseSess,
+                    loader: &mut CrateLoader,
                     cfg: ast::CrateConfig,
                     c: Crate) -> Crate {
-    let mut cx = ExtCtxt::new(parse_sess, cfg.clone());
+    let mut cx = ExtCtxt::new(parse_sess, cfg.clone(), loader);
     let mut expander = MacroExpander {
         extsbox: syntax_expander_table(),
         cx: &mut cx,
@@ -1076,6 +1142,7 @@ mod test {
     use codemap::Spanned;
     use fold;
     use fold::*;
+    use ext::base::{CrateLoader, MacroCrate};
     use parse;
     use parse::token::{fresh_mark, gensym, intern, ident_to_str};
     use parse::token;
@@ -1119,6 +1186,22 @@ pub fn new_path_finder(paths: ~[ast::Path]) -> NewPathExprFinderContext {
         }
     }
 
+    struct ErrLoader;
+
+    impl CrateLoader for ErrLoader {
+        fn load_crate(&mut self, _: &ast::ViewItem) -> MacroCrate {
+            fail!("lolwut")
+        }
+
+        fn get_exported_macros(&mut self, _: ast::CrateNum) -> ~[@ast::Item] {
+            fail!("lolwut")
+        }
+
+        fn get_registrar_symbol(&mut self, _: ast::CrateNum) -> Option<~str> {
+            fail!("lolwut")
+        }
+    }
+
     // make sure that fail! is present
     #[test] fn fail_exists_test () {
         let src = @"fn main() { fail!(\"something appropriately gloomy\");}";
@@ -1129,7 +1212,8 @@ pub fn new_path_finder(paths: ~[ast::Path]) -> NewPathExprFinderContext {
             ~[],sess);
         let crate_ast = inject_std_macros(sess, ~[], crate_ast);
         // don't bother with striping, doesn't affect fail!.
-        expand_crate(sess,~[],crate_ast);
+        let mut loader = ErrLoader;
+        expand_crate(sess,&mut loader,~[],crate_ast);
     }
 
     // these following tests are quite fragile, in that they don't test what
@@ -1146,7 +1230,8 @@ pub fn new_path_finder(paths: ~[ast::Path]) -> NewPathExprFinderContext {
             src,
             ~[],sess);
         // should fail:
-        expand_crate(sess,~[],crate_ast);
+        let mut loader = ErrLoader;
+        expand_crate(sess,&mut loader,~[],crate_ast);
     }
 
     // make sure that macros can leave scope for modules
@@ -1160,7 +1245,8 @@ pub fn new_path_finder(paths: ~[ast::Path]) -> NewPathExprFinderContext {
             src,
             ~[],sess);
         // should fail:
-        expand_crate(sess,~[],crate_ast);
+        let mut loader = ErrLoader;
+        expand_crate(sess,&mut loader,~[],crate_ast);
     }
 
     // macro_escape modules shouldn't cause macros to leave scope
@@ -1173,7 +1259,8 @@ pub fn new_path_finder(paths: ~[ast::Path]) -> NewPathExprFinderContext {
             src,
             ~[], sess);
         // should fail:
-        expand_crate(sess,~[],crate_ast);
+        let mut loader = ErrLoader;
+        expand_crate(sess,&mut loader,~[],crate_ast);
     }
 
     #[test] fn std_macros_must_parse () {
@@ -1281,7 +1368,8 @@ fn renaming () {
     fn expand_crate_str(crate_str: @str) -> ast::Crate {
         let (crate_ast,ps) = string_to_crate_and_sess(crate_str);
         // the cfg argument actually does matter, here...
-        expand_crate(ps,~[],crate_ast)
+        let mut loader = ErrLoader;
+        expand_crate(ps,&mut loader,~[],crate_ast)
     }
 
     //fn expand_and_resolve(crate_str: @str) -> ast::crate {
index a4b8dd7840327877a4609bed2375bbdcf92adc41..33832a8c62d41e389a8be50f84bac7f4df989a5b 100644 (file)
@@ -34,7 +34,7 @@ enum Position {
 }
 
 struct Context<'a> {
-    ecx: &'a mut ExtCtxt,
+    ecx: &'a mut ExtCtxt<'a>,
     fmtsp: Span,
 
     // Parsed argument expressions and the types that we've found so far for
@@ -634,17 +634,24 @@ fn to_expr(&self, extra: @ast::Expr) -> @ast::Expr {
                                      self.ecx.expr_ident(e.span, lname)));
         }
 
+        // Now create a vector containing all the arguments
+        let slicename = self.ecx.ident_of("__args_vec");
+        {
+            let args = names.move_iter().map(|a| a.unwrap());
+            let mut args = locals.move_iter().chain(args);
+            let args = self.ecx.expr_vec_slice(self.fmtsp, args.collect());
+            lets.push(self.ecx.stmt_let(self.fmtsp, false, slicename, args));
+        }
+
         // Now create the fmt::Arguments struct with all our locals we created.
-        let args = names.move_iter().map(|a| a.unwrap());
-        let mut args = locals.move_iter().chain(args);
         let fmt = self.ecx.expr_ident(self.fmtsp, static_name);
-        let args = self.ecx.expr_vec_slice(self.fmtsp, args.collect());
+        let args_slice = self.ecx.expr_ident(self.fmtsp, slicename);
         let result = self.ecx.expr_call_global(self.fmtsp, ~[
                 self.ecx.ident_of("std"),
                 self.ecx.ident_of("fmt"),
                 self.ecx.ident_of("Arguments"),
                 self.ecx.ident_of("new"),
-            ], ~[fmt, args]);
+            ], ~[fmt, args_slice]);
 
         // We did all the work of making sure that the arguments
         // structure is safe, so we can safely have an unsafe block.
index e66e394d639563e680e709c1375052ef8d323999..27f41356a4bb39d0ac046d1b5e4f3020f71ca7d8 100644 (file)
@@ -243,7 +243,7 @@ pub trait ExtParseUtils {
         fn parse_tts(&self, s: @str) -> ~[ast::TokenTree];
     }
 
-    impl ExtParseUtils for ExtCtxt {
+    impl<'a> ExtParseUtils for ExtCtxt<'a> {
 
         fn parse_item(&self, s: @str) -> @ast::Item {
             let res = parse::parse_item_from_source_str(
diff --git a/src/libsyntax/ext/registrar.rs b/src/libsyntax/ext/registrar.rs
new file mode 100644 (file)
index 0000000..265dd91
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ast;
+use attr;
+use codemap::Span;
+use diagnostic;
+use visit;
+use visit::Visitor;
+
+struct MacroRegistrarContext {
+    registrars: ~[(ast::NodeId, Span)],
+}
+
+impl Visitor<()> for MacroRegistrarContext {
+    fn visit_item(&mut self, item: &ast::Item, _: ()) {
+        match item.node {
+            ast::ItemFn(..) => {
+                if attr::contains_name(item.attrs, "macro_registrar") {
+                    self.registrars.push((item.id, item.span));
+                }
+            }
+            _ => {}
+        }
+
+        visit::walk_item(self, item, ());
+    }
+}
+
+pub fn find_macro_registrar(diagnostic: @diagnostic::SpanHandler,
+                            crate: &ast::Crate) -> Option<ast::DefId> {
+    let mut ctx = MacroRegistrarContext { registrars: ~[] };
+    visit::walk_crate(&mut ctx, crate, ());
+
+    match ctx.registrars.len() {
+        0 => None,
+        1 => {
+            let (node_id, _) = ctx.registrars.pop();
+            Some(ast::DefId {
+                crate: ast::LOCAL_CRATE,
+                node: node_id
+            })
+        },
+        _ => {
+            diagnostic.handler().err("Multiple macro registration functions found");
+            for &(_, span) in ctx.registrars.iter() {
+                diagnostic.span_note(span, "one is here");
+            }
+            diagnostic.handler().abort_if_errors();
+            unreachable!();
+        }
+    }
+}
index d3862cdf1a168bcd615344e0ce0c12454d4ac460..7a86dd6e4ce72d70548f2e940c6afcd261307ac4 100644 (file)
@@ -63,20 +63,7 @@ fn fold_view_paths(&mut self, view_paths: &[@ViewPath]) -> ~[@ViewPath] {
     }
 
     fn fold_view_item(&mut self, vi: &ViewItem) -> ViewItem {
-        let inner_view_item = match vi.node {
-            ViewItemExternMod(ref ident, string, node_id) => {
-                ViewItemExternMod(ident.clone(), string, self.new_id(node_id))
-            }
-            ViewItemUse(ref view_paths) => {
-                ViewItemUse(self.fold_view_paths(*view_paths))
-            }
-        };
-        ViewItem {
-            node: inner_view_item,
-            attrs: vi.attrs.map(|a| fold_attribute_(*a, self)),
-            vis: vi.vis,
-            span: self.new_span(vi.span),
-        }
+        noop_fold_view_item(vi, self)
     }
 
     fn fold_foreign_item(&mut self, ni: @ForeignItem) -> @ForeignItem {
@@ -319,7 +306,7 @@ fn fold_explicit_self(&mut self, es: &ExplicitSelf) -> ExplicitSelf {
 
     fn fold_explicit_self_(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
         match *es {
-            SelfStatic | SelfValue(_) | SelfUniq(_) | SelfBox(_) => {
+            SelfStatic | SelfValue(_) | SelfUniq(_) | SelfBox => {
                 *es
             }
             SelfRegion(ref lifetime, m) => {
@@ -509,6 +496,28 @@ fn fold_variant_arg_<T: Folder>(va: &VariantArg, folder: &mut T) -> VariantArg {
     }
 }
 
+pub fn noop_fold_view_item<T: Folder>(vi: &ViewItem, folder: &mut T)
+                                       -> ViewItem{
+    let inner_view_item = match vi.node {
+        ViewItemExternMod(ref ident,
+                             string,
+                             node_id) => {
+            ViewItemExternMod(ident.clone(),
+                                 string,
+                                 folder.new_id(node_id))
+        }
+        ViewItemUse(ref view_paths) => {
+            ViewItemUse(folder.fold_view_paths(*view_paths))
+        }
+    };
+    ViewItem {
+        node: inner_view_item,
+        attrs: vi.attrs.map(|a| fold_attribute_(*a, folder)),
+        vis: vi.vis,
+        span: folder.new_span(vi.span),
+    }
+}
+
 pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
     let view_items = b.view_items.map(|x| folder.fold_view_item(x));
     let stmts = b.stmts.iter().flat_map(|s| folder.fold_stmt(*s).move_iter()).collect();
index 7eebbc75f946fd371ab267e5972fa65393ca4edd..532a2a9a314935a148ad552c085b64226de8fa3c 100644 (file)
@@ -68,6 +68,7 @@ pub mod ext {
     pub mod asm;
     pub mod base;
     pub mod expand;
+    pub mod registrar;
 
     pub mod quote;
 
index 247962e0b94243ef4f2626d8fc05f04293f5f4ef..326f712d5b2124f245133ece6ffb6c0e7e2878f6 100644 (file)
@@ -42,12 +42,31 @@ pub fn push(&mut self, t: T) {
                 v.push(t);
                 return;
             }
-            Empty => {}
+            Empty => {
+                *self = Vec(~[t]);
+            }
         }
+    }
+
+    pub fn pop(&mut self) -> T {
+        match *self {
+            Vec(ref mut v) => v.pop(),
+            Empty => fail!("pop from empty opt_vec")
+        }
+    }
 
-        // FIXME(#5074): flow insensitive means we can't move
-        // assignment inside `match`
-        *self = Vec(~[t]);
+    pub fn last<'a>(&'a self) -> &'a T {
+        match *self {
+            Vec(ref v) => v.last(),
+            Empty => fail!("last on empty opt_vec")
+        }
+    }
+
+    pub fn mut_last<'a>(&'a mut self) -> &'a mut T {
+        match *self {
+            Vec(ref mut v) => v.mut_last(),
+            Empty => fail!("mut_last on empty opt_vec")
+        }
     }
 
     pub fn map<U>(&self, op: |&T| -> U) -> OptVec<U> {
@@ -82,6 +101,16 @@ pub fn len(&self) -> uint {
         }
     }
 
+    pub fn swap_remove(&mut self, index: uint) {
+        match *self {
+            Empty => { fail!("Index out of bounds"); }
+            Vec(ref mut v) => {
+                assert!(index < v.len());
+                v.swap_remove(index);
+            }
+        }
+    }
+
     #[inline]
     pub fn iter<'r>(&'r self) -> OptVecIterator<'r, T> {
         match *self {
@@ -166,6 +195,16 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
+impl<'a, T> DoubleEndedIterator<&'a T> for OptVecIterator<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a T> {
+        match self.iter {
+            Some(ref mut x) => x.next_back(),
+            None => None
+        }
+    }
+}
+
 impl<A> FromIterator<A> for OptVec<A> {
     fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> OptVec<A> {
         let mut r = Empty;
index 30a662c9cceda70338b28c387b2e65e5a8040fef..b1a80878cf1b5b5d1f6a573d3211bf715ec7119b 100644 (file)
@@ -12,7 +12,7 @@
 
 
 use ast;
-use codemap::{Span, CodeMap, FileMap, FileSubstr};
+use codemap::{Span, CodeMap, FileMap};
 use codemap;
 use diagnostic::{SpanHandler, mk_span_handler, mk_handler, Emitter};
 use parse::attr::ParserAttr;
@@ -180,27 +180,6 @@ pub fn parse_tts_from_source_str(
     maybe_aborted(p.parse_all_token_trees(),p)
 }
 
-// given a function and parsing information (source str,
-// filename, crate cfg, and sess), create a parser,
-// apply the function, and check that the parser
-// consumed all of the input before returning the function's
-// result.
-pub fn parse_from_source_str<T>(
-                             f: |&mut Parser| -> T,
-                             name: @str,
-                             ss: codemap::FileSubstr,
-                             source: @str,
-                             cfg: ast::CrateConfig,
-                             sess: @ParseSess)
-                             -> T {
-    let mut p = new_parser_from_source_substr(sess, cfg, name, ss, source);
-    let r = f(&mut p);
-    if !p.reader.is_eof() {
-        p.reader.fatal(~"expected end-of-string");
-    }
-    maybe_aborted(r,p)
-}
-
 // Create a new parser from a source string
 pub fn new_parser_from_source_str(sess: @ParseSess,
                                   cfg: ast::CrateConfig,
@@ -210,17 +189,6 @@ pub fn new_parser_from_source_str(sess: @ParseSess,
     filemap_to_parser(sess,string_to_filemap(sess,source,name),cfg)
 }
 
-// Create a new parser from a source string where the origin
-// is specified as a substring of another file.
-pub fn new_parser_from_source_substr(sess: @ParseSess,
-                                  cfg: ast::CrateConfig,
-                                  name: @str,
-                                  ss: codemap::FileSubstr,
-                                  source: @str)
-                               -> Parser {
-    filemap_to_parser(sess,substring_to_filemap(sess,source,name,ss),cfg)
-}
-
 /// Create a new parser, handling errors as appropriate
 /// if the file doesn't exist
 pub fn new_parser_from_file(
@@ -297,13 +265,6 @@ pub fn string_to_filemap(sess: @ParseSess, source: @str, path: @str)
     sess.cm.new_filemap(path, source)
 }
 
-// given a session and a string and a path and a FileSubStr, add
-// the string to the CodeMap and return the new FileMap
-pub fn substring_to_filemap(sess: @ParseSess, source: @str, path: @str,
-                           filesubstr: FileSubstr) -> @FileMap {
-    sess.cm.new_filemap_w_substr(path,filesubstr,source)
-}
-
 // given a filemap, produce a sequence of token-trees
 pub fn filemap_to_tts(sess: @ParseSess, filemap: @FileMap)
     -> ~[ast::TokenTree] {
@@ -457,7 +418,7 @@ fn sp(a: u32, b: u32) -> Span {
 
     #[test] fn string_to_tts_1 () {
         let tts = string_to_tts(@"fn a (b : int) { b; }");
-        assert_eq!(to_json_str(@tts),
+        assert_eq!(to_json_str(&tts),
         ~"[\
     {\
         \"variant\":\"TTTok\",\
index 715ce644726ab888d235eeee53efec9270a418de..e79c845b24d4868ea2595384fb70673bb686e788 100644 (file)
@@ -142,8 +142,6 @@ enum ItemOrViewItem {
 macro_rules! maybe_whole_expr (
     ($p:expr) => (
         {
-            // This horrible convolution is brought to you by
-            // @mut, have a terrible day
             let mut maybe_path = match ($p).token {
                 INTERPOLATED(token::NtPath(ref pt)) => Some((**pt).clone()),
                 _ => None,
@@ -2025,7 +2023,7 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: @Expr) -> @Expr {
                     seq_sep_trailing_disallowed(token::COMMA),
                     |p| p.parse_expr()
                 );
-                hi = self.span.hi;
+                hi = self.last_span.hi;
 
                 let nd = self.mk_call(e, es, NoSugar);
                 e = self.mk_expr(lo, hi, nd);
@@ -2035,7 +2033,7 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: @Expr) -> @Expr {
               token::LBRACKET => {
                 self.bump();
                 let ix = self.parse_expr();
-                hi = ix.span.hi;
+                hi = self.span.hi;
                 self.commit_expr_expecting(ix, token::RBRACKET);
                 let index = self.mk_index(e, ix);
                 e = self.mk_expr(lo, hi, index)
@@ -3647,20 +3645,14 @@ fn expect_self_ident(&mut self) {
     // that may have a self type.
     fn parse_fn_decl_with_self(&mut self, parse_arg_fn: |&mut Parser| -> Arg)
                                -> (ExplicitSelf, P<FnDecl>) {
-        fn maybe_parse_explicit_self(cnstr: |v: Mutability| ->
-                                        ast::ExplicitSelf_,
+        fn maybe_parse_explicit_self(explicit_self: ast::ExplicitSelf_,
                                      p: &mut Parser)
                                      -> ast::ExplicitSelf_ {
             // We need to make sure it isn't a type
-            if p.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) ||
-                ((p.look_ahead(1, |t| token::is_keyword(keywords::Const, t)) ||
-                  p.look_ahead(1, |t| token::is_keyword(keywords::Mut, t))) &&
-                 p.look_ahead(2, |t| token::is_keyword(keywords::Self, t))) {
-
+            if p.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
                 p.bump();
-                let mutability = p.parse_mutability();
                 p.expect_self_ident();
-                cnstr(mutability)
+                explicit_self
             } else {
                 SelfStatic
             }
@@ -3719,55 +3711,47 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
         // backwards compatible.
         let lo = self.span.lo;
         let explicit_self = match self.token {
-          token::BINOP(token::AND) => {
-            maybe_parse_borrowed_explicit_self(self)
-          }
-          token::AT => {
-            maybe_parse_explicit_self(SelfBox, self)
-          }
-          token::TILDE => {
-            maybe_parse_explicit_self(|mutability| {
-                if mutability != MutImmutable {
-                    self.span_err(self.last_span,
-                                  "mutability declaration not allowed here");
+            token::BINOP(token::AND) => {
+                maybe_parse_borrowed_explicit_self(self)
+            }
+            token::AT => {
+                maybe_parse_explicit_self(SelfBox, self)
+            }
+            token::TILDE => {
+                maybe_parse_explicit_self(SelfUniq(MutImmutable), self)
+            }
+            token::IDENT(..) if self.is_self_ident() => {
+                self.bump();
+                SelfValue(MutImmutable)
+            }
+            token::BINOP(token::STAR) => {
+                // Possibly "*self" or "*mut self" -- not supported. Try to avoid
+                // emitting cryptic "unexpected token" errors.
+                self.bump();
+                let mutability = if Parser::token_is_mutability(&self.token) {
+                    self.parse_mutability()
+                } else { MutImmutable };
+                if self.is_self_ident() {
+                    self.span_err(self.span, "cannot pass self by unsafe pointer");
+                    self.bump();
                 }
-                SelfUniq(MutImmutable)
-            }, self)
-          }
-          token::IDENT(..) if self.is_self_ident() => {
-            self.bump();
-            SelfValue(MutImmutable)
-          }
-          token::BINOP(token::STAR) => {
-            // Possibly "*self" or "*mut self" -- not supported. Try to avoid
-            // emitting cryptic "unexpected token" errors.
-            self.bump();
-            let mutability = if Parser::token_is_mutability(&self.token) {
-                self.parse_mutability()
-            } else { MutImmutable };
-            if self.is_self_ident() {
-                self.span_err(self.span, "cannot pass self by unsafe pointer");
+                SelfValue(mutability)
+            }
+            _ if Parser::token_is_mutability(&self.token) &&
+                    self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
+                let mutability = self.parse_mutability();
+                self.expect_self_ident();
+                SelfValue(mutability)
+            }
+            _ if Parser::token_is_mutability(&self.token) &&
+                    self.look_ahead(1, |t| *t == token::TILDE) &&
+                    self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
+                let mutability = self.parse_mutability();
                 self.bump();
+                self.expect_self_ident();
+                SelfUniq(mutability)
             }
-            SelfValue(mutability)
-          }
-          _ if Parser::token_is_mutability(&self.token) &&
-               self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
-            let mutability = self.parse_mutability();
-            self.expect_self_ident();
-            SelfValue(mutability)
-          }
-          _ if Parser::token_is_mutability(&self.token) &&
-               self.look_ahead(1, |t| *t == token::TILDE) &&
-               self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
-            let mutability = self.parse_mutability();
-            self.bump();
-            self.expect_self_ident();
-            SelfUniq(mutability)
-          }
-          _ => {
-            SelfStatic
-          }
+            _ => SelfStatic
         };
 
         // If we parsed a self type, expect a comma before the argument list.
index 3275ba2cef52419de4dce4ccc9f1185c597544ea..a6fceb086c9192a88d5e5b987fd4bff2e8ca7d2f 100644 (file)
@@ -1770,8 +1770,8 @@ pub fn print_explicit_self(s: &mut State, explicit_self: ast::ExplicitSelf_) ->
             print_mutability(s, m);
             word(&mut s.s, "self");
         }
-        ast::SelfBox(m) => {
-            word(&mut s.s, "@"); print_mutability(s, m); word(&mut s.s, "self");
+        ast::SelfBox => {
+            word(&mut s.s, "@self");
         }
     }
     return true;
index ffea4b6dc751082fb4d1d90b3cd1367f19267f21..484f8dce1f745c685d4124c258c1d04949c7b392 100644 (file)
@@ -121,6 +121,17 @@ fn visit_path(&mut self, path: &Path, _id: ast::NodeId, e: E) {
     }
 }
 
+pub fn walk_inlined_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
+                                                  item: &ast::InlinedItem,
+                                                  env: E) {
+    match *item {
+        IIItem(i) => visitor.visit_item(i, env),
+        IIForeign(i) => visitor.visit_foreign_item(i, env),
+        IIMethod(_, _, m) => walk_method_helper(visitor, m, env),
+    }
+}
+
+
 pub fn walk_crate<E: Clone, V: Visitor<E>>(visitor: &mut V, crate: &Crate, env: E) {
     visitor.visit_mod(&crate.module, crate.span, CRATE_NODE_ID, env)
 }
@@ -175,7 +186,7 @@ fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                explicit_self: &ExplicitSelf,
                                                env: E) {
     match explicit_self.node {
-        SelfStatic | SelfValue(_) | SelfBox(_) | SelfUniq(_) => {}
+        SelfStatic | SelfValue(_) | SelfBox | SelfUniq(_) => {}
         SelfRegion(ref lifetime, _) => {
             visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
         }
index 1fb05b89381234044dfb9be29114187976926e24..280df8cb10f57d9ce4018a796a95f3d118f905ae 100644 (file)
@@ -522,6 +522,17 @@ extern "C" char *LLVMTypeToString(LLVMTypeRef Type) {
     return strdup(os.str().data());
 }
 
+extern "C" char *LLVMValueToString(LLVMValueRef Value) {
+    std::string s;
+    llvm::raw_string_ostream os(s);
+    os << "(";
+    unwrap<llvm::Value>(Value)->getType()->print(os);
+    os << ":";
+    unwrap<llvm::Value>(Value)->print(os);
+    os << ")";
+    return strdup(os.str().data());
+}
+
 extern "C" bool
 LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
     Module *Dst = unwrap(dst);
index e95b9ed988eb4906f3e865195cda8de617c9a961..368b2a0fd38a737024d2e2a85f33fc65152e2b9f 100644 (file)
@@ -1,3 +1,11 @@
+S 2014-01-14 29070c3
+  freebsd-x86_64 c2fb6e6313a9f1d41df810fcf1ae354858a8bf76
+  linux-i386 6437656b81cf9f3d1377523c1e36d5cf06b2d645
+  linux-x86_64 f3ca80c146f3a6495c19fc77dba13f9c0abece49
+  macos-i386 3f1f9925fe1ddca94f2727194bd5763b0705016e
+  macos-x86_64 0c10e160e3a754f2cdc89aea037c458fefe03d30
+  winnt-i386 5cb277524157a8a883a8641b829f8aa6f53cdcf8
+
 S 2014-01-08 f3a8baa
   freebsd-x86_64 9f2491ebe48ff77774c73c111acdd951973d7e47
   linux-i386 e2ba50e6a7d0cf6a7d65393f0c6416a2af58f8d4
diff --git a/src/test/auxiliary/macro_crate_def_only.rs b/src/test/auxiliary/macro_crate_def_only.rs
new file mode 100644 (file)
index 0000000..145212b
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+#[feature(macro_rules)];
+
+#[macro_export]
+macro_rules! make_a_5(
+    () => (5)
+)
diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs
new file mode 100644 (file)
index 0000000..403bbac
--- /dev/null
@@ -0,0 +1,42 @@
+// 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.
+
+#[feature(globs, macro_registrar, macro_rules)];
+
+extern mod syntax;
+
+use syntax::ast::{Name, TokenTree};
+use syntax::codemap::Span;
+use syntax::ext::base::*;
+use syntax::parse::token;
+
+#[macro_export]
+macro_rules! exported_macro (() => (2))
+
+macro_rules! unexported_macro (() => (3))
+
+#[macro_registrar]
+pub fn macro_registrar(register: |Name, SyntaxExtension|) {
+    register(token::intern("make_a_1"),
+        NormalTT(~SyntaxExpanderTT {
+            expander: SyntaxExpanderTTExpanderWithoutContext(expand_make_a_1),
+            span: None,
+        },
+        None));
+}
+
+pub fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> MacResult {
+    if !tts.is_empty() {
+        cx.span_fatal(sp, "make_a_1 takes no arguments");
+    }
+    MRExpr(quote_expr!(cx, 1i))
+}
+
+pub fn foo() {}
diff --git a/src/test/compile-fail/borrowck-borrow-from-temporary.rs b/src/test/compile-fail/borrowck-borrow-from-temporary.rs
new file mode 100644 (file)
index 0000000..a2f5e28
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+// Test lifetimes are linked properly when we take reference
+// to interior.
+
+struct Foo(int);
+
+fn foo() -> &int {
+    let &Foo(ref x) = &Foo(3); //~ ERROR borrowed value does not live long enough
+    x
+}
+
+pub fn main() {
+}
diff --git a/src/test/compile-fail/borrowck-reborrow-from-shorter-lived-andmut.rs b/src/test/compile-fail/borrowck-reborrow-from-shorter-lived-andmut.rs
new file mode 100644 (file)
index 0000000..85ddfd9
--- /dev/null
@@ -0,0 +1,31 @@
+// 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.
+
+// Test that assignments to an `&mut` pointer which is found in a
+// borrowed (but otherwise non-aliasable) location is illegal.
+
+struct S<'a> {
+    pointer: &'a mut int
+}
+
+fn copy_borrowed_ptr<'a,'b>(p: &'a mut S<'b>) -> S<'b> {
+    S { pointer: &mut *p.pointer } //~ ERROR lifetime of `p` is too short to guarantee its contents can be safely reborrowed
+}
+
+fn main() {
+    let mut x = 1;
+
+    {
+        let mut y = S { pointer: &mut x };
+        let z = copy_borrowed_ptr(&mut y);
+        *y.pointer += 1;
+        *z.pointer += 1;
+    }
+}
diff --git a/src/test/compile-fail/borrowck-rvalues-mutable-bad.rs b/src/test/compile-fail/borrowck-rvalues-mutable-bad.rs
deleted file mode 100644 (file)
index 10bef90..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Tests that rvalue lifetimes is limited to the enclosing trans
-// cleanup scope. It is unclear that this is the correct lifetime for
-// rvalues, but that's what it is right now.
-
-struct Counter {
-    value: uint
-}
-
-impl Counter {
-    fn new(v: uint) -> Counter {
-        Counter {value: v}
-    }
-
-    fn inc<'a>(&'a mut self) -> &'a mut Counter {
-        self.value += 1;
-        self
-    }
-
-    fn get(&self) -> uint {
-        self.value
-    }
-}
-
-pub fn main() {
-    let v = Counter::new(22).inc().inc().get();
-    //~^ ERROR borrowed value does not live long enough
-    assert_eq!(v, 24);;
-}
diff --git a/src/test/compile-fail/cleanup-rvalue-scopes-cf.rs b/src/test/compile-fail/cleanup-rvalue-scopes-cf.rs
new file mode 100644 (file)
index 0000000..47b7b51
--- /dev/null
@@ -0,0 +1,45 @@
+// 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.
+
+// Test that the borrow checker prevents pointers to temporaries
+// with statement lifetimes from escaping.
+
+#[feature(macro_rules)];
+
+use std::ops::Drop;
+
+static mut FLAGS: u64 = 0;
+
+struct Box<T> { f: T }
+struct AddFlags { bits: u64 }
+
+fn AddFlags(bits: u64) -> AddFlags {
+    AddFlags { bits: bits }
+}
+
+fn arg<'a>(x: &'a AddFlags) -> &'a AddFlags {
+    x
+}
+
+impl AddFlags {
+    fn get<'a>(&'a self) -> &'a AddFlags {
+        self
+    }
+}
+
+pub fn main() {
+    let _x = arg(&AddFlags(1)); //~ ERROR value does not live long enough
+    let _x = AddFlags(1).get(); //~ ERROR value does not live long enough
+    let _x = &*arg(&AddFlags(1)); //~ ERROR value does not live long enough
+    let ref _x = *arg(&AddFlags(1)); //~ ERROR value does not live long enough
+    let &ref _x = arg(&AddFlags(1)); //~ ERROR value does not live long enough
+    let _x = AddFlags(1).get(); //~ ERROR value does not live long enough
+    let Box { f: _x } = Box { f: AddFlags(1).get() }; //~ ERROR value does not live long enough
+}
diff --git a/src/test/compile-fail/gated-macro_registrar.rs b/src/test/compile-fail/gated-macro_registrar.rs
new file mode 100644 (file)
index 0000000..54274cc
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// the registration function isn't typechecked yet
+#[macro_registrar]
+pub fn registrar() {} //~ ERROR cross-crate macro exports are experimental
+
+fn main() {}
diff --git a/src/test/compile-fail/gated-phase.rs b/src/test/compile-fail/gated-phase.rs
new file mode 100644 (file)
index 0000000..3a801e1
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_crate_test.rs
+
+#[phase(syntax)]
+//~^ ERROR compile time crate loading is experimental and possibly buggy
+extern mod macro_crate_test;
+
+fn main() {}
diff --git a/src/test/compile-fail/macro-crate-unexported-macro.rs b/src/test/compile-fail/macro-crate-unexported-macro.rs
new file mode 100644 (file)
index 0000000..d6867e7
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+// aux-build:macro_crate_test.rs
+// xfail-stage1
+
+#[feature(phase)];
+
+#[phase(syntax)]
+extern mod macro_crate_test;
+
+fn main() {
+    assert_eq!(3, unexported_macro!()); //~ ERROR macro undefined: 'unexported_macro'
+}
diff --git a/src/test/compile-fail/macro-crate-unknown-crate.rs b/src/test/compile-fail/macro-crate-unknown-crate.rs
new file mode 100644 (file)
index 0000000..83538fc
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[feature(phase)];
+
+#[phase(syntax)]
+extern mod doesnt_exist; //~ ERROR can't find crate
+
+fn main() {}
diff --git a/src/test/compile-fail/multiple-macro-registrars.rs b/src/test/compile-fail/multiple-macro-registrars.rs
new file mode 100644 (file)
index 0000000..7802c13
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern: Multiple macro registration functions found
+
+#[feature(macro_registrar)];
+
+// the registration function isn't typechecked yet
+#[macro_registrar]
+pub fn one() {}
+
+#[macro_registrar]
+pub fn two() {}
+
+fn main() {}
diff --git a/src/test/compile-fail/phase-syntax-doesnt-resolve.rs b/src/test/compile-fail/phase-syntax-doesnt-resolve.rs
new file mode 100644 (file)
index 0000000..c7e49d2
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_crate_test.rs
+// xfail-stage1
+
+#[feature(phase)];
+
+#[phase(syntax)]
+extern mod macro_crate_test;
+
+fn main() {
+    macro_crate_test::foo();
+    //~^ ERROR unresolved name
+    //~^^ ERROR use of undeclared module `macro_crate_test`
+    //~^^^ ERROR unresolved name `macro_crate_test::foo`.
+}
index 19e52305a4eac492aa29e0ff487ebbdf04db3e68..8fb9c5e0e6f840b561f5edb348de210e47b1be94 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -11,5 +11,6 @@
 struct S;
 
 impl S {
-    fn f(~mut self) {} //~ ERROR mutability declaration not allowed here
+    fn f(~mut self) {} //~ ERROR found `self` in ident position
+    //~^ ERROR expected `:` but found `)`
 }
index bbe453594bc96ecd735de48086b7b48794f49195..0d415a85172b6613fc161fbe0bfc930a885813d4 100644 (file)
@@ -196,13 +196,13 @@ fn main() {
     let Unit(ii) = Unit(51);
 
     // univariant enum with ref      binding
-    let Unit(ref jj) = Unit(52);
+    let &Unit(ref jj) = &Unit(52);
 
     // tuple struct
-    let TupleStruct(kk, ll) = TupleStruct(53.0, 54);
+    let &TupleStruct(kk, ll) = &TupleStruct(53.0, 54);
 
     // tuple struct with ref binding
-    let TupleStruct(mm, ref nn) = TupleStruct(55.0, 56);
+    let &TupleStruct(mm, ref nn) = &TupleStruct(55.0, 56);
 
     zzz();
 }
index 337af1ed86f4ec5c7c43645ddb3d9f9b945d50e6..8eed28170c57d2d08996ebdfaba46bba86ac85e8 100644 (file)
 // debugger:run
 // debugger:finish
 
-// debugger:print unique->val.elements[0]->val
+// debugger:print unique->elements[0]->val
 // check:$1 = 10
 
-// debugger:print unique->val.elements[1]->val
+// debugger:print unique->elements[1]->val
 // check:$2 = 11
 
-// debugger:print unique->val.elements[2]->val
+// debugger:print unique->elements[2]->val
 // check:$3 = 12
 
-// debugger:print unique->val.elements[3]->val
+// debugger:print unique->elements[3]->val
 // check:$4 = 13
 
 #[allow(unused_variable)];
index db75b4bd4befab55827fd021bac3b20ca07d1828..4afc8b235edb6e9cd8d85e15273e9760d5d8d21e 100644 (file)
 // debugger:print *ordinary_unique
 // check:$1 = {-1, -2}
 
-// debugger:print managed_within_unique.val->x
+// debugger:print managed_within_unique->x
 // check:$2 = -3
 
-// debugger:print managed_within_unique.val->y->val
+// debugger:print managed_within_unique->y->val
 // check:$3 = -4
 
 #[allow(unused_variable)];
 
-struct ContainsManaged
-{
-       x: int,
-       y: @int
+struct ContainsManaged {
+    x: int,
+    y: @int
 }
 
 fn main() {
+    let ordinary_unique = ~(-1, -2);
 
-       let ordinary_unique = ~(-1, -2);
-
-
-       // This is a special case: Normally values allocated in the exchange heap are not boxed, unless,
-       // however, if they contain managed pointers.
-       // This test case verifies that both cases are handled correctly.
     let managed_within_unique = ~ContainsManaged { x: -3, y: @-4 };
 
     zzz();
index 20c8cc27f271b3f54d78f819c3d4ec2d6f2a7316..cf693d7e35623342f9efc4bcf0b43fa2de3ba905 100644 (file)
@@ -49,9 +49,9 @@
 // debugger:print stack_managed.next.val->val.value
 // check:$12 = 11
 
-// debugger:print unique_managed->val.value
+// debugger:print unique_managed->value
 // check:$13 = 12
-// debugger:print unique_managed->val.next.val->val.value
+// debugger:print unique_managed->next.val->val.value
 // check:$14 = 13
 
 // debugger:print box_managed->val.value
index cf5a9341c9dc437747d91eb7d32c27fd94bdd6e3..d4de4ef34d39729d821b2a535bd07741e3cc4676 100644 (file)
@@ -17,6 +17,15 @@ fn new(v: uint) -> Counter {
         Counter {value: v}
     }
 
+    fn inc<'a>(&'a mut self) -> &'a mut Counter {
+        self.value += 1;
+        self
+    }
+
+    fn get(&self) -> uint {
+        self.value
+    }
+
     fn get_and_inc(&mut self) -> uint {
         let v = self.value;
         self.value += 1;
@@ -27,4 +36,7 @@ fn get_and_inc(&mut self) -> uint {
 pub fn main() {
     let v = Counter::new(22).get_and_inc();
     assert_eq!(v, 22);
+
+    let v = Counter::new(22).inc().inc().get();
+    assert_eq!(v, 24);;
 }
diff --git a/src/test/run-pass/cleanup-arm-conditional.rs b/src/test/run-pass/cleanup-arm-conditional.rs
new file mode 100644 (file)
index 0000000..afe1489
--- /dev/null
@@ -0,0 +1,43 @@
+// copyright 2014 the rust project developers. see the copyright
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/copyright.
+//
+// licensed under the apache license, version 2.0 <license-apache or
+// http://www.apache.org/licenses/license-2.0> or the mit license
+// <license-mit or http://opensource.org/licenses/mit>, at your
+// option. this file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that cleanup scope for temporaries created in a match
+// arm is confined to the match arm itself.
+
+use std::{os, run};
+use std::io::process;
+
+struct Test { x: int }
+
+impl Test {
+    fn get_x(&self) -> Option<~int> {
+        Some(~self.x)
+    }
+}
+
+fn do_something(t: &Test) -> int {
+
+    // The cleanup scope for the result of `t.get_x()` should be the
+    // arm itself and not the match, otherwise we'll (potentially) get
+    // a crash trying to free an uninitialized stack slot.
+
+    match t {
+        &Test { x: 2 } if t.get_x().is_some() => {
+            t.x * 2
+        }
+        _ => { 22 }
+    }
+}
+
+pub fn main() {
+    let t = Test { x: 1 };
+    do_something(&t);
+}
+
diff --git a/src/test/run-pass/cleanup-rvalue-for-scope.rs b/src/test/run-pass/cleanup-rvalue-for-scope.rs
new file mode 100644 (file)
index 0000000..68441a2
--- /dev/null
@@ -0,0 +1,70 @@
+// 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.
+
+// Test that the lifetime of rvalues in for loops is extended
+// to the for loop itself.
+
+#[feature(macro_rules)];
+
+use std::ops::Drop;
+
+static mut FLAGS: u64 = 0;
+
+struct Box<T> { f: T }
+struct AddFlags { bits: u64 }
+
+fn AddFlags(bits: u64) -> AddFlags {
+    AddFlags { bits: bits }
+}
+
+fn arg(exp: u64, _x: &AddFlags) {
+    check_flags(exp);
+}
+
+fn pass<T>(v: T) -> T {
+    v
+}
+
+fn check_flags(exp: u64) {
+    unsafe {
+        let x = FLAGS;
+        FLAGS = 0;
+        println!("flags {}, expected {}", x, exp);
+        assert_eq!(x, exp);
+    }
+}
+
+impl AddFlags {
+    fn check_flags<'a>(&'a self, exp: u64) -> &'a AddFlags {
+        check_flags(exp);
+        self
+    }
+
+    fn bits(&self) -> u64 {
+        self.bits
+    }
+}
+
+impl Drop for AddFlags {
+    fn drop(&mut self) {
+        unsafe {
+            FLAGS = FLAGS + self.bits;
+        }
+    }
+}
+
+pub fn main() {
+    // The array containing [AddFlags] should not be dropped until
+    // after the for loop:
+    for x in [AddFlags(1)].iter() {
+        check_flags(0);
+    }
+    check_flags(1);
+}
diff --git a/src/test/run-pass/cleanup-rvalue-scopes.rs b/src/test/run-pass/cleanup-rvalue-scopes.rs
new file mode 100644 (file)
index 0000000..7ed59ec
--- /dev/null
@@ -0,0 +1,137 @@
+// 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.
+
+// Test that destructors for rvalue temporaries run either at end of
+// statement or end of block, as appropriate given the temporary
+// lifetime rules.
+
+#[feature(macro_rules)];
+
+use std::ops::Drop;
+
+static mut FLAGS: u64 = 0;
+
+struct Box<T> { f: T }
+struct AddFlags { bits: u64 }
+
+fn AddFlags(bits: u64) -> AddFlags {
+    AddFlags { bits: bits }
+}
+
+fn arg(exp: u64, _x: &AddFlags) {
+    check_flags(exp);
+}
+
+fn pass<T>(v: T) -> T {
+    v
+}
+
+fn check_flags(exp: u64) {
+    unsafe {
+        let x = FLAGS;
+        FLAGS = 0;
+        println!("flags {}, expected {}", x, exp);
+        assert_eq!(x, exp);
+    }
+}
+
+impl AddFlags {
+    fn check_flags<'a>(&'a self, exp: u64) -> &'a AddFlags {
+        check_flags(exp);
+        self
+    }
+
+    fn bits(&self) -> u64 {
+        self.bits
+    }
+}
+
+impl Drop for AddFlags {
+    fn drop(&mut self) {
+        unsafe {
+            FLAGS = FLAGS + self.bits;
+        }
+    }
+}
+
+macro_rules! end_of_block(
+    ($pat:pat, $expr:expr) => (
+        {
+            println!("end_of_block({})", stringify!({let $pat = $expr;}));
+
+            {
+                // Destructor here does not run until exit from the block.
+                let $pat = $expr;
+                check_flags(0);
+            }
+            check_flags(1);
+        }
+    )
+)
+
+macro_rules! end_of_stmt(
+    ($pat:pat, $expr:expr) => (
+        {
+            println!("end_of_stmt({})", stringify!($expr));
+
+            {
+                // Destructor here run after `let` statement
+                // terminates.
+                let $pat = $expr;
+                check_flags(1);
+            }
+
+            check_flags(0);
+        }
+    )
+)
+
+pub fn main() {
+
+    // In all these cases, we trip over the rules designed to cover
+    // the case where we are taking addr of rvalue and storing that
+    // addr into a stack slot, either via `let ref` or via a `&` in
+    // the initializer.
+
+    end_of_block!(_x, AddFlags(1));
+    end_of_block!(_x, &AddFlags(1));
+    end_of_block!(_x, & &AddFlags(1));
+    end_of_block!(_x, Box { f: AddFlags(1) });
+    end_of_block!(_x, Box { f: &AddFlags(1) });
+    end_of_block!(_x, Box { f: &AddFlags(1) });
+    end_of_block!(_x, pass(AddFlags(1)));
+    end_of_block!(ref _x, AddFlags(1));
+    end_of_block!(AddFlags { bits: ref _x }, AddFlags(1));
+    end_of_block!(&AddFlags { bits }, &AddFlags(1));
+    end_of_block!((_, ref _y), (AddFlags(1), 22));
+    end_of_block!(~ref _x, ~AddFlags(1));
+    end_of_block!(~_x, ~AddFlags(1));
+    end_of_block!(_, { { check_flags(0); &AddFlags(1) } });
+    end_of_block!(_, &((Box { f: AddFlags(1) }).f));
+    end_of_block!(_, &(([AddFlags(1)])[0]));
+    end_of_block!(_, &((&~[AddFlags(1)])[0]));
+
+    // LHS does not create a ref binding, so temporary lives as long
+    // as statement, and we do not move the AddFlags out:
+    end_of_stmt!(_, AddFlags(1));
+    end_of_stmt!((_, _), (AddFlags(1), 22));
+
+    // `&` operator appears inside an arg to a function,
+    // so it is not prolonged:
+    end_of_stmt!(ref _x, arg(0, &AddFlags(1)));
+
+    // autoref occurs inside receiver, so temp lifetime is not
+    // prolonged:
+    end_of_stmt!(ref _x, AddFlags(1).check_flags(0).bits());
+
+    // No reference is created on LHS, thus RHS is moved into
+    // a temporary that lives just as long as the statement.
+    end_of_stmt!(AddFlags { bits }, AddFlags(1));
+}
diff --git a/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs b/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs
new file mode 100644 (file)
index 0000000..53a009e
--- /dev/null
@@ -0,0 +1,39 @@
+// Test cleanup of rvalue temporary that occurs while `~` construction
+// is in progress. This scenario revealed a rather terrible bug.  The
+// ingredients are:
+//
+// 1. Partial cleanup of `~` is in scope,
+// 2. cleanup of return value from `get_bar()` is in scope,
+// 3. do_it() fails.
+//
+// This led to a bug because `the top-most frame that was to be
+// cleaned (which happens to be the partial cleanup of `~`) required
+// multiple basic blocks, which led to us dropping part of the cleanup
+// from the top-most frame.
+//
+// It's unclear how likely such a bug is to recur, but it seems like a
+// scenario worth testing.
+
+use std::task;
+
+enum Conzabble {
+    Bickwick(Foo)
+}
+
+struct Foo { field: ~uint }
+
+fn do_it(x: &[uint]) -> Foo {
+    fail!()
+}
+
+fn get_bar(x: uint) -> ~[uint] { ~[x * 2] }
+
+pub fn fails() {
+    let x = 2;
+    let mut y = ~[];
+    y.push(~Bickwick(do_it(get_bar(x))));
+}
+
+pub fn main() {
+    task::try(fails);
+}
diff --git a/src/test/run-pass/cleanup-shortcircuit.rs b/src/test/run-pass/cleanup-shortcircuit.rs
new file mode 100644 (file)
index 0000000..982a0d9
--- /dev/null
@@ -0,0 +1,30 @@
+// 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.
+
+// Test that cleanups for the RHS of shorcircuiting operators work.
+
+use std::{os, run};
+use std::io::process;
+
+pub fn main() {
+    let args = os::args();
+
+    // Here, the rvalue `~"signal"` requires cleanup. Older versions
+    // of the code had a problem that the cleanup scope for this
+    // expression was the end of the `if`, and as the `~"signal"`
+    // expression was never evaluated, we wound up trying to clean
+    // uninitialized memory.
+
+    if args.len() >= 2 && args[1] == ~"signal" {
+        // Raise a segfault.
+        unsafe { *(0 as *mut int) = 0; }
+    }
+}
+
index 1d2b0197f08e1dadfe9e22c4acc9739786630969..f42d5ff2e5267b00f48951111397e486b2471f6a 100644 (file)
@@ -8,20 +8,22 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[feature(managed_boxes)];
+use std::cast::transmute;
 
 mod rusti {
     extern "rust-intrinsic" {
+        pub fn init<T>() -> T;
         pub fn move_val_init<T>(dst: &mut T, src: T);
-        pub fn move_val<T>(dst: &mut T, src: T);
     }
 }
 
 pub fn main() {
     unsafe {
-        let x = @1;
-        let mut y = @2;
-        rusti::move_val(&mut y, x);
+        let x = ~1;
+        let mut y = rusti::init();
+        let mut z: *uint = transmute(&x);
+        rusti::move_val_init(&mut y, x);
         assert_eq!(*y, 1);
+        assert_eq!(*z, 0); // `x` is nulled out, not directly visible
     }
 }
index 020db44bb87a612dca305faead033cae95c67068..4d5ed9f701a394ea85353d0478bc8c84e74b1a32 100644 (file)
@@ -30,10 +30,10 @@ pub fn main () {
 
     let config = process::ProcessConfig {
         program : args[0].as_slice(),
-        args : [~"child"],
+        args : &[~"child"],
         env : None,
         cwd : None,
-        io : []
+        io : &[]
     };
 
     let mut p = process::Process::new(config).unwrap();
index a5f87e6c5365dcc8a824522e0131989f033cfe8b..f6bbd8ebef86a68931626115809893873bafa1a3 100644 (file)
@@ -28,10 +28,10 @@ struct Thing2<'a> {
 
 pub fn main() {
     let _t1_fixed = Thing1 {
-        baz: [],
+        baz: &[],
         bar: ~32,
     };
-    let _t1_uniq = Thing1 {
+    Thing1 {
         baz: ~[],
         bar: ~32,
     };
@@ -40,10 +40,10 @@ pub fn main() {
         bar: ~32,
     };
     let _t2_fixed = Thing2 {
-        baz: [],
+        baz: &[],
         bar: 32,
     };
-    let _t2_uniq = Thing2 {
+    Thing2 {
         baz: ~[],
         bar: 32,
     };
diff --git a/src/test/run-pass/macro-crate-def-only.rs b/src/test/run-pass/macro-crate-def-only.rs
new file mode 100644 (file)
index 0000000..b5ae00e
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+// aux-build:macro_crate_def_only.rs
+// xfail-fast
+
+#[feature(phase)];
+
+#[phase(syntax)]
+extern mod macro_crate_def_only;
+
+pub fn main() {
+    assert_eq!(5, make_a_5!());
+}
diff --git a/src/test/run-pass/macro-crate.rs b/src/test/run-pass/macro-crate.rs
new file mode 100644 (file)
index 0000000..0073c1c
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+// aux-build:macro_crate_test.rs
+// xfail-stage1
+// xfail-fast
+
+#[feature(phase)];
+
+#[phase(syntax)]
+extern mod macro_crate_test;
+
+pub fn main() {
+    assert_eq!(1, make_a_1!());
+    assert_eq!(2, exported_macro!());
+}
index c3335a0d45570c2cfb156a761034b09299614cc7..983c701d820319874dcda2080801f016112b040c 100644 (file)
@@ -15,6 +15,7 @@ struct Triple { x: int, y: int, z: int }
 fn test(x: bool, foo: @Triple) -> int {
     let bar = foo;
     let mut y: @Triple;
+    y = bar;
     if x { y = bar; } else { y = @Triple{x: 4, y: 5, z: 6}; }
     return y.y;
 }
diff --git a/src/test/run-pass/phase-syntax-link-does-resolve.rs b/src/test/run-pass/phase-syntax-link-does-resolve.rs
new file mode 100644 (file)
index 0000000..20c6fa5
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_crate_test.rs
+// xfail-stage1
+// xfail-fast
+
+#[feature(phase)];
+
+#[phase(syntax, link)]
+extern mod macro_crate_test;
+
+fn main() {
+    assert_eq!(1, make_a_1!());
+    macro_crate_test::foo();
+}
index 8fc27cf8ea3b16578548f2bc279ccb57f0786c74..e244eace65be626078c4f95eb9ca47f138a4bbe6 100644 (file)
@@ -223,13 +223,6 @@ fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         true
     }
 
-    fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~u8>();
-        if ! self.inner().visit_uniq_managed(mtbl, inner) { return false; }
-        self.bump_past::<~u8>();
-        true
-    }
-
     fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<*u8>();
         if ! self.inner().visit_ptr(mtbl, inner) { return false; }
@@ -275,13 +268,6 @@ fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         true
     }
 
-    fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~[@u8]>();
-        if ! self.inner().visit_evec_uniq_managed(mtbl, inner) { return false; }
-        self.bump_past::<~[@u8]>();
-        true
-    }
-
     fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<&'static [u8]>();
         if ! self.inner().visit_evec_slice(mtbl, inner) { return false; }
@@ -549,7 +535,6 @@ fn visit_estr_fixed(&mut self, _n: uint, _sz: uint,
 
     fn visit_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
 
@@ -557,7 +542,6 @@ fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_unboxed_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_evec_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint,
                         _mtbl: uint, _inner: *TyDesc) -> bool { true }
index de50bb3bfed9b1abe8bba0b117837e9e5559d686..f5871facd1da21666312e4ab2d2a56516e9d5d97 100644 (file)
@@ -70,7 +70,6 @@ fn visit_estr_fixed(&mut self,
 
     fn visit_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
 
@@ -83,12 +82,6 @@ fn visit_evec_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
         self.types.push(~"]");
         true
     }
-    fn visit_evec_uniq_managed(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
-        self.types.push(~"[");
-        unsafe { visit_tydesc(inner, &mut *self as &mut TyVisitor) };
-        self.types.push(~"]");
-        true
-    }
     fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint,
                         _mtbl: uint, _inner: *TyDesc) -> bool { true }
diff --git a/src/test/run-pass/regions-dependent-let-ref.rs b/src/test/run-pass/regions-dependent-let-ref.rs
new file mode 100644 (file)
index 0000000..980fcfb
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+// Test lifetimes are linked properly when we take reference
+// to interior.
+
+struct Foo(int);
+pub fn main() {
+    // Here the lifetime of the `&` should be at least the
+    // block, since a ref binding is created to the interior.
+    let &Foo(ref _x) = &Foo(3);
+}
diff --git a/src/test/run-pass/uninit-empty-types.rs b/src/test/run-pass/uninit-empty-types.rs
new file mode 100644 (file)
index 0000000..4a5c859
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+// Test the uninit() construct returning various empty types.
+
+use std::vec;
+use std::unstable::intrinsics;
+
+#[deriving(Clone)]
+struct Foo;
+
+pub fn main() {
+    unsafe {
+        let _x: Foo = intrinsics::uninit();
+        let _x: [Foo, ..2] = intrinsics::uninit();
+    }
+}